我知道这是不赞成的,但我在这里没有选择。我正在开发一个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文件?
答案 0 :(得分:4)
你能以/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 :(得分:1)
首先,这不适用于表单。
在使用Windows窗体的应用程序中,未处理的异常 主应用程序线程导致 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"));
答案 2 :(得分:1)
我建议您尝试__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投入大量时间的人,我可以同情你的困境。希望这个解决方案有所帮助。
有关C ++ / CLI异常处理的其他MSDN文档:
如何:定义和安装全局异常处理程序 http://msdn.microsoft.com/en-us/library/171ezxzc.aspx
/ clr下的异常处理 http://msdn.microsoft.com/en-us/library/633chdda.aspx
答案 3 :(得分:0)
有几种类型的异常处理。您发布的内容仅处理托管例外。
C ++代码也可能抛出非托管异常(特别是来自标准库)。此外,非托管代码可能会抛出Win32异常。
Start here并阅读结构化异常处理(Win32异常)。 C ++异常和托管异常是基于SEH构建的,因此如果您在流程中每个线程的顶点处理SEH,您将受到保护。
答案 4 :(得分:0)
并非每次崩溃都是例外,至少不会立即发生。一个狂野的指针完全有可能踩踏.NET内部数据结构,以至于当抛出异常时,托管处理程序无法正常运行。
尝试使用本机处理程序。 Visual C ++提供了__try
/ __except
,但是您需要确保处理程序位于程序中每个线程的调用堆栈上,并且仍然可以对异常进行未处理(例如CreateThread)用指针指向非法指令)。要处理所有边缘情况,您应该使用SetUnhandledExceptionFilter
。
请注意,对于/clr:pure
,所有代码都依赖于CLR,因此会因运行时损坏而失败。即使是原生处理程序也可能依赖于已损坏的状态,尽管它们不如基于MSIL的处理程序脆弱。为了实现强大的错误处理,您确实需要在流程外部运行代码。