VC++程序捕获所有异常

前两天同事说他客户端有时候crash了抓不到dump,问我有没有遇到类似情况。在Windows平台,抓不到dump原因大概有以下几种情况:

我之前写过一篇博客 DbgHelp教程3——Minidump 简单介绍了异常的处理回调函数,但是不够完整。这篇博客更详细的介绍VC++程序处理异常。

Windows异常处理框架

Windows异常处理分为两种,SEH(Structured Exception Handling) 和 VEH(Vectored Exception Handling)。主要是一些Windows系统支持的一些异常,比如访问无效的内存地址、除0错误、数组越界等等,如 Exception Code 所显示。

SEH 通过一些关键字__try__except__finally__leave,定义了一套自己的异常处理。而VEH允许使用AddVectoredExceptionHandler来注册一到多个回调函数来处理异常。

因为有多个异常处理函数,他们之间处理的顺序是:

  1. VEH 异常处理函数
  2. SEH 异常处理函数
  3. SetUnhandledExceptionFilter注册的异常处理函数

CRT异常处理

Windows的异常处理捕获不到CRT里面一些异常。因此我们需要对其设置做一些设置:

  1. _set_invalid_parameter_handler 设置处理无效的参数异常
  2. _set_purecall_handler 设置处理虚函数异常
  3. set_terminate 设置处理terminate异常
  4. signal(SIGABRT, abort_handler) 设置处理abort异常
  5. _set_new_handler 设置处理new内存失败异常
  6. _set_new_mode(1) 设置处理malloc内存失败异常跟new行为一样

dump处理

为了尽可能的捕获异常来生成dump,通常通过SetUnhandledExceptionFilter注册最后全局的异常处理函数,它可以捕获进程内所有线程的Windows异常。然后Hook住SetUnhandledExceptionFilter函数,阻止后续其他代码再调用它,以免覆盖我们自己的异常处理函数。

对于CRT的异常,在其异常处理函数里调用__debugbreak();,从而触发一个Windows上的异常,再被SetUnhandledExceptionFilter设置的回调函数捕获到。然而CRT的异常处理函数也存在被后续代码设置回调函数覆盖的问题,处理同SetUnhandledExceptionFilter

参考