在所有错误情况下,我需要采取什么行动来获得崩溃转储?

我们在Windows上,并且我们想要在应用程序出口的所有场景中出现故障转储(可能使用MiniDumpWriteDump )。

到目前为止,我们已经确定并build立了以下内容:

  • SetUnhandledExceptionFilter对于未处理的exception(Win32以及“正常”的C ++)。
  • 用于CRT无效参数处理的_set_invalid_parameter_handler
  • _set_abort_behavior加上一个SIGABRT处理程序来说明对abort()调用

有什么我们错过了吗? (模一些代码非法调用ExitProcessTerminateProcess或其中一个exit变体。)

我使用的是你已经列出的,加上_set_purecall_handler ,加上这个方便的代码片段:

 void EnableCrashingOnCrashes() { typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags); typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags); static const DWORD EXCEPTION_SWALLOWING = 0x1; const HMODULE kernel32 = LoadLibraryA("kernel32.dll"); const tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy"); const tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy"); if(pGetPolicy && pSetPolicy) { DWORD dwFlags; if(pGetPolicy(&dwFlags)) { // Turn off the filter pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING); } } } 

资料来源: http : //randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/

在他的网站上的这些其他文章也帮助我了解这一点: http : //randomascii.wordpress.com/2011/12/07/increased-reliability-through-more-crashes/ http://randomascii.wordpress.com/2012/ 7月22日/更多的冒险,在-没有到崩溃正确/

SetUnhandledExceptionFilter强调不足以捕获所有意外退出。 如果应用程序不小心调用纯虚函数,则会弹出一个对话框。 应用程序将挂起,但不会崩溃。 既然没有例外,SetUnhandledExceptionFilter和WER都不能帮助。 这个主题有一些变化。

更糟糕的是,如果你在内核回调(比如WindowProc)中崩溃的话,那将是一个怪事。 如果在64位Windows上的32位应用程序中发生这种情况,则操作系统将捕获该异常,并继续执行。 是的,这个事故是无声无息的。 我觉得很可怕

http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/应详细说明处理这些不寻常情况所需的所有技巧。

高低顺序,简而言之:

  • 你不需要使用任何其他的_set*函数, SetUnhandledExceptionFilter就足够了。
  • abort这样的C运行时函数将禁用全局异常处理程序,您可以使用SetUnhandledExceptionFilter设置。 CRT将简单地调用这个相同的函数将NULL参数,并且你的异常处理程序被禁用(不叫),如果CRT导致崩溃! 你可以做什么? [X]
  • 当excption-handler被调用时禁用所有其他正在运行的线程。 只需使用CreateToolhelp32Snapshot和其他函数查找所有线程CreateToolhelp32Snapshot 。 寻找这个过程,并暂停所有其他正在运行的线程(当前除外)。
  • 使用SEH或no-SEH,全局异常处理程序被调用,除非CRT中断。 不用担心(在大多数情况下)。
  • 如果任何CLR /托管调用(来自C / C ++的是)之间,则不允许异常处理程序调用它们之间的任何CLR。
  • 你不能处理一个异常 – 堆栈溢出! 认为! 在调试器下运行只是解决方案,请参阅下文。

还有更多,我没有尝试(没有发现有用) – 向量异常处理。

另一种方法是将应用程序运行到调试器,您可以自己制作! 在调试器中,您可以捕获所有异常,就像VS调试器捕获的一样。 看我的文章 。 但是,你知道,这是不正确的做法。

编辑:只要阅读关于进程终止的最后一个内容。 你不应该控制这个。 在任何情况下,您都可以挂接所需的API,这将作为您的代码(如显示消息框)。

[X]您需要使用API​​挂钩。 我没有链接和细节方便。 你会挂钩其他相关的API,但主要是SetUnhandledExceptionFilter (在你之后为你调用)。 您虚拟(挂钩)函数将如下所示:

 xxx SetUnhandledExceptionFilter_DUMMY(xxx) { // Dont do any thing return NULL; } 

我没有API挂钩的方便链接和细节。


为什么不试图让你的应用程序更安全?

  • 纠正所有的警告(是的,甚至4级)。
  • 使用静态分析。 VS本身(更高版本,除了2012年 – 所有变种都有)。 其他SA工具可用。
  • 做仔细的代码审查。 它付出!
  • 从调试器运行并调试您的RELEASE版本。 使用所有功能。
  • 查看并纠正所有可能的内存泄漏。
  • 使用防御性的方法来编程。 而不是检查是否为空,使用ASSERT或您自己的断言进行辩护。 将它与断言,日志,从函数返回打包。

我将添加一个解决方案,在Windows 7上运行时可以在某些情况下使用:

Windows错误报告(WER)提供了在应用程序崩溃时编写完整内存转储的选项。

所以,如果你没有问题的话,你只需要确保你真正感兴趣的崩溃情景会触发WER。 这真的让我们回到这个问题,但仍然…

您可以使用WER捕获任何异常。 正如你所看到的,CRT有时候会被叫做WER。

如果您想要始终在进程中捕获excpetion,则需要防止从CRT调用SetUnhandledExceptionFilter(NULL) 。 欲了解更多信息,请参阅我的博客条目: 改进“PreventSetUnhandledExceptionFilter”