C ++ / CLI: отлов всех исключений (.NET / Win32 / CRT) - PullRequest
7 голосов
/ 08 июля 2011

Я знаю, что это осуждается, но у меня нет вариантов здесь. Я занимаюсь разработкой приложения на C ++ / CLI, в котором есть ошибка, которую я не могу отследить - в основном потому, что она игнорирует мой текущий обработчик сбоев:

AppDomain::CurrentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(&LogAndExit);
Application::ThreadException += gcnew ThreadExceptionEventHandler(&LogAndExit);
Application::SetUnhandledExceptionMode(UnhandledExceptionMode::CatchException);
try 
{ 
    Application::Run(gcnew frmMain()); 
} 
catch (Exception^ ex) 
{ 
    LogAndExit(ex); 
} 
catch (...) 
{ 
    LogAndExit(); 
}

Стандартная обработка аварий .NET, я полагаю. MSDN сообщает, что некоторые из исключений CRT переместятся через управляемый стек и автоматически прекратят работу приложения.

Я читал _set_invalid_parameter_handler, но даже при получении ошибки LNK2001, похоже, ее нельзя использовать с / clr: pure. Я прав, или я просто PEBKAC это и отсутствует файл lib?

Ответы [ 5 ]

4 голосов
/ 17 августа 2011

Можете ли вы работать в режиме /clr? Если вы можете попробовать это:

#include <exception>

Тогда:

try
{
    try
    {
        Application::Run(gcnew frmMain()); 
    }
    catch(const exception& ex)
    {
        throw gcnew System::Exception(gcnew System::String(ex.what()));
    }
} 
catch (Exception^ ex) 
{ 
    LogAndExit(ex); 
} 
catch (...) 
{ 
    LogAndExit(); 
}

Еще один момент, на который следует обратить внимание: , если ваше приложение является многопоточным, вы поймаете исключение только из потока, в котором работает frmMain(). Таким образом, в этом случае невозможно охватить все ваше приложение!

1 голос
/ 17 августа 2011

Я рекомендую вам попробовать __try / __except

__try 
{ 
  Application::Run(gcnew frmMain()); 
} 
__except(EXCEPTION_EXECUTE_HANDLER) 
{ 
  LogAndExit(new Exception("Some Unmanage exception")); 
}

Документация MSDN здесь:

http://msdn.microsoft.com/en-us/library/s58ftw19(v=vs.80).aspx

Если вы хотите стать действительно хитрым, вы можете попробовать дважды обернуть его так:

__try 
{ 
  try {
    Application::Run(gcnew frmMain()); 
  } 
  catch(SEHException^ e)
  {
    LogAndExit(new Exception("Some Unmanage exception")); 
  }
  catch(...) //Leave this out if you're /clr:pure
  {
    LogAndExit(new Exception("Some Unmanage exception")); 
  }
} 
__except(EXCEPTION_EXECUTE_HANDLER) 
{ 
  LogAndExit(new Exception("Some Unmanage exception")); 
}

Структурированные исключения включаются в SEHException ^ обычно.

Вам также необходимо принять во внимание, что на самом деле вы можете перехватывать исключение, но что-то в вашем методе LogAndExit вызывает вторичное исключение, которое фактически завершает вашу программу. Попробуйте заглушить функцию LogAndExit и посмотрите, сможете ли вы заставить аварийный сбой произойти тихо, а не с помощью стандартного сообщения об отмене, и / или оберните свой код LogAndExit в другой try / catch, который скрывает любые исключения.

Как человек, который уделил много времени C ++ / CLI, я могу сочувствовать вашей дилемме. Надеюсь, что это решение поможет.

Дополнительная документация MSDN по обработке исключений в C ++ / CLI:

Как: определить и установить глобальный обработчик исключений http://msdn.microsoft.com/en-us/library/171ezxzc.aspx

Обработка исключений в / clr http://msdn.microsoft.com/en-us/library/633chdda.aspx

1 голос
/ 08 июля 2011

Прежде всего, это не работает для форм.

В приложениях, использующих Windows Forms, необработанные исключения в основной поток приложения вызывают Application.ThreadException событие для быть поднятым. Если это событие обрабатывается, поведение по умолчанию заключается в том, что необработанное исключение не прекращается приложение, хотя заявка оставлена ​​в неизвестном государство. В этом случае Событие UnhandledException не является поднял. Такое поведение можно изменить с помощью конфигурации приложения файл или с помощью Application.SetUnhandledExceptionMode способ изменить режим на UnhandledExceptionMode.ThrowException до события ThreadException обработчик подключен. Это относится только в основной ветке приложения. Возникает событие UnhandledException за необработанные исключения, добавленные в другие темы.

Во-вторых, может быть неуправляемое исключение (которое не относится к типу System :: Exception ).

try { Application::Run(gcnew frmMain()); } 
catch (Exception^ ex) { LogAndExit(ex); }
catch (...) { LogAndExit(new Exception("Some Unmanage exception"));

msdn - Как перехватывать исключения в Visual C ++

0 голосов
/ 08 июля 2011

Не каждый сбой является исключением, по крайней мере, не сразу. Для дикого указателя вполне возможно растоптать внутренние структуры данных .NET настолько сильно, что при возникновении исключения управляемый обработчик не может работать правильно.

Попробуйте вместо этого использовать собственный обработчик. Visual C ++ обеспечивает __try / __except, но вам нужно убедиться, что обработчик находится в стеке вызовов каждого потока в вашей программе, и все еще возможно, что исключение останется необработанным (например, CreateThread с указателем на незаконная инструкция). Чтобы иметь дело со всеми крайними случаями, вы должны вместо этого использовать SetUnhandledExceptionFilter.

Обратите внимание, что при /clr:pure весь код зависит от CLR и может быть поврежден из-за повреждения во время выполнения. Даже собственные обработчики могут зависеть от поврежденного состояния, хотя они менее хрупки, чем обработчики на основе MSIL. Для надежной обработки ошибок вам действительно нужен код, работающий вне процесса.

0 голосов
/ 08 июля 2011

Существует несколько типов обработки исключений.То, что вы опубликовали, будет обрабатывать только управляемые исключения.

Также возможно, чтобы код C ++ генерировал неуправляемые исключения (особенно из стандартной библиотеки).Кроме того, неуправляемый код может генерировать исключение Win32.

Начните здесь и ознакомьтесь со структурной обработкой исключений (исключения Win32).Исключения C ++ и управляемые исключения построены на SEH, поэтому, если вы обрабатываете SEH в верхней точке каждого потока в вашем процессе, вы будете защищены.

...