如何快速调试并找到在std::thread子线程中抛出的C++异常问题!
C++11标准库新增的std::thread类可以方便地开启子线程。然而有个奇怪的现象是,如果在这些子线程中抛出了未处理的C++异常而导致程序崩溃,那么在生成的dump文件中将还原不出异常发生时的调用栈。可以通过下面的方法来展示这个现象。 首先使用以下代码生成一个控制台程序: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # include <thread> # include <vector> std::thread* g_thread; void ThreadEntry () { std::vector< int > v; v. at ( 0 ); } int main () { g_thread = new std:: thread (ThreadEntry); g_thread-> join (); } 这段代码很简单,就是通过std::thread创建一个子线程,并且在这个子线程中访问一个空的std::vector中的元素,让它抛出C++异常。务必要使用Release配置来生成程序,不能使用Debug配置。 接下来,在资源管理器中直接运行该程序,注意不要通过调试器来运行。一般会在第二次运行的时候,出现下面的Windows错误报告窗口: 在详细信息中的C:\Users\Zplutor\AppData\Local\Temp\WERBF98.tmp.mdmp文件即是Windows错误报告为崩溃的程序生成的dump文件,里面包含了程序崩溃时的一些信息,例如函数调用栈。该文件在关闭了错误报告窗口时即被删除,所以要先把这个文件复制出来。 最后,用WinDbg打开这个dump文件,先用.ecxr命令切换到异常环境,再用k命令显示调用栈,结果显示如下: 1 2 3 4 5 6 7 8 9 10 11 0:002> k *** Stack trace for last set context - .thread/.cxr resets it ChildEBP RetAddr 0095f07c 6ba8dc5f msvcr120!abort+0x38 [f:\dd\vctools\crt\crtw32\misc\abort.c @ 90] 009