调试服务器程序时最怕遇到需要运行10天半个月才遇到一次的bug,这种bug很难还原现场,同时还要时刻注意服务器是否挂掉。
本文给出一个解决方法可以极大的提高调试效率。
使用本文方法可以在断言失败时自动dump,可用于还原bug环境进行调试。另外崩溃时也会自动记录crash dump。
断言函数
bool xassert(bool r){
if(!r) __asm int 3 return r; }
最终异常处理函数,遇到这里的话说明程序只能挂掉了,写crash dump
LONG WINAPI LastExceptionHandler(PEXCEPTION_POINTERS pEi){ auto h=CreateFile("crash.dmp",GENERIC_WRITE,0,nullptr,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,nullptr); if(h!=INVALID_HANDLE_VALUE){ MINIDUMP_EXCEPTION_INFORMATION mei; mei.ClientPointers=false; mei.ThreadId=GetCurrentThreadId(); mei.ExceptionPointers=pEi; MiniDumpWriteDump(GetCurrentProcess(),GetCurrentProcessId(),h,MiniDumpWithPrivateReadWriteMemory,&mei,nullptr,nullptr); CloseHandle(h); } return EXCEPTION_CONTINUE_SEARCH; }
最先异常处理函数,用于处理xassert里面的int 3,写调试dump
LONG WINAPI FirstExceptionHandler(PEXCEPTION_POINTERS pEi){
switch(pEi->ExceptionRecord->ExceptionCode){ //所有的软件断点都是我提交的 case EXCEPTION_BREAKPOINT://软件断点int3 0xcc { static int nDump=0; static char tmp[1024]; _snprintf_s(tmp,1000,"debug%02d.dmp",++nDump); auto h=CreateFile(tmp,GENERIC_WRITE,0,nullptr,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,nullptr); if(h!=INVALID_HANDLE_VALUE){ MINIDUMP_EXCEPTION_INFORMATION mei; mei.ClientPointers=false; mei.ThreadId=GetCurrentThreadId(); mei.ExceptionPointers=pEi; MiniDumpWriteDump(GetCurrentProcess(),GetCurrentProcessId(),h,MiniDumpWithPrivateReadWriteMemory,&mei,nullptr,nullptr); CloseHandle(h); } pEi->ContextRecord->Eip+=1; return EXCEPTION_CONTINUE_EXECUTION; }break; case EXCEPTION_SINGLE_STEP://debug 硬件断点 { }break; } return EXCEPTION_CONTINUE_SEARCH; }
最后在程序初始化时加上
AddVectoredExceptionHandler(0,FirstExceptionHandler); SetUnhandledExceptionFilter(LastExceptionHandler);
代码原理。
xassert失败时执行一个int3指令,产生调试中断
使用异常处理函数捕获调试中断,用debugAPI写dump后恢复到调试指令下一条继续执行。
最终异常处理函数捕获所有未能处理的异常,写crash dump后程序自动崩溃。
时间: 2024-10-29 06:06:38