《Linux部分》 【Linux => Debug模式】 测试:https://github.com/bombela/backward-cpp 仅头文件的库,配合#define BACKWARD_HAS_BFD 1和sudo apt install binutils-dev 可以实现Debug下精准找点。 也有apt-get install libdw-dev(#define BACKWARD_HAS_DW 1)和 apt-get install libdwarf-dev(#define BACKWARD_HAS_DWARF 1)这两个没测试。 使用方法为: #define BACKWARD_HAS_BFD 1 #include "backward.hpp" #include #include #include #include void sig_handler(int sig) { backward::StackTrace st; st.load_here(32); backward::Printer p; p.print(st); std::ofstream fs("stacktrace.log"); p.print(st, fs); fs.close(); exit(1); } void th_sim() { std::this_thread::sleep_for(std::chrono::seconds(5)); // throw "Erro Auto"; int* p = nullptr; *p = 33; } int main() { signal(SIGSEGV, sig_handler); signal(SIGABRT, sig_handler); signal(SIGFPE, sig_handler); std::thread t(th_sim); std::cout << "Done" << std::endl; t.join(); return 0; } 编译链接:target_link_libraries(dmeo PRIVATE bfd dl) 《Windows部分》 【Windows => Debug模式】 #include "backward.hpp" #include 使用方法: LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* exception) { backward::StackTrace st; st.load_from(exception->ContextRecord); backward::Printer p; // 输出到控制台 p.print(st, std::cerr); // 输出到文件 std::ofstream fs("stacktrace.log"); p.print(st, fs); fs.close(); return EXCEPTION_EXECUTE_HANDLER; // 终止程序 } 显示初始化:backward::SignalHandling sh;而且必须在SetUnhandledExceptionFilter(ExceptionHandler); 后面。 如下: #include #include #include "backward.hpp" #include using namespace std; LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* exception) { backward::StackTrace st; st.load_from(exception->ContextRecord); backward::Printer p; // 输出到控制台 p.print(st, std::cerr); // 输出到文件 std::ofstream fs("stacktrace.log"); p.print(st, fs); fs.close(); return EXCEPTION_EXECUTE_HANDLER; // 终止程序 } void th_sim() { std::this_thread::sleep_for(std::chrono::seconds(5)); // throw "Erro Auto"; int* p = nullptr; *p = 33; } int main() { SetUnhandledExceptionFilter(ExceptionHandler); // 注册全局异常处理 backward::SignalHandling sh; // std::set_terminate(terminate_handler); std::thread t(th_sim); std::cout << "Done" << std::endl; t.join(); return 0; } 编译链接: target_link_libraries(dumpdemo PRIVATE DbgHelp) 【Windows => Release模式】 实际测试,如果想生成dmp文件,就不能使用backward库(两者选一个)(不使用backward::SignalHandling sh;)。 void CreateMiniDump(EXCEPTION_POINTERS* exception) { HANDLE hFile = CreateFile("crash114.dmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return; }; MINIDUMP_EXCEPTION_INFORMATION info; info.ThreadId = GetCurrentThreadId(); info.ExceptionPointers = exception; info.ClientPointers = TRUE; MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &info, NULL, NULL ); CloseHandle(hFile); } 使用backward堆栈信息打印有限,如下(测试代码见上方): Done Stack trace (most recent call last): #3 Object "", at 00007FFBD4A4E8D7, in BaseThreadInitThunk #2 Object "", at 00007FFBD31C37B0, in wcsrchr 试图访问无效的地址。 #1 Object "", at 00007FF691A2208B, in ?? 试图访问无效的地址。 #0 Object "", at 00007FF691A27EC2, in ?? 而使用WinDbg分析Dump文件,信息如下: FILE_IN_CAB: crash114.dmp CONTEXT: (.ecxr) rax=0000000000000000 rbx=0000019f92279e60 rcx=00000018c2d828f9 rdx=00000018ca1b2b0e rsi=00004e94914f0000 rdi=000009ac1b967bb8 rip=00007ff7b2f41682 rsp=00000084c57ff970 rbp=0000000000000000 r8=0000000000000083 r9=000000007ffe7000 r10=0000000000000001 r11=fffffffff8bcfdeb r12=0000000000000000 r13=0000000000000000 r14=b2f4fc0794908cf3 r15=0000000000000000 iopl=0 nv up ei pl zr na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 dumpdemo+0x1682: 00007ff7`b2f41682 c70021000000 mov dword ptr [rax],21h ds:00000000`00000000=???????? Resetting default scope EXCEPTION_RECORD: (.exr -1) ExceptionAddress: 00007ff7b2f41682 (dumpdemo+0x0000000000001682) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 0000000000000001 Parameter[1]: 0000000000000000 Attempt to write to address 0000000000000000 PROCESS_NAME: dumpdemo.exe WRITE_ADDRESS: 0000000000000000 ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p %s EXCEPTION_CODE_STR: c0000005 EXCEPTION_PARAMETER1: 0000000000000001 EXCEPTION_PARAMETER2: 0000000000000000 STACK_TEXT: 00000084`c57ff970 00007ff7`b2f4126b : 000009aa`f19089b8 0000019f`92279e60 00000000`00000000 00000000`00000000 : dumpdemo+0x1682 00000084`c57ff9b0 00007ffb`d31c37b0 : 0000019f`92275720 00000000`00000000 00000000`00000000 00000000`00000000 : dumpdemo+0x126b 00000084`c57ff9e0 00007ffb`d4a4e8d7 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ucrtbase!thread_start+0x30 00000084`c57ffa10 00007ffb`d5b314fc : 00000000`00000000 00000000`00000000 000004f0`fffffb30 000004d0`fffffb30 : kernel32!BaseThreadInitThunk+0x17 00000084`c57ffa40 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x2c STACK_COMMAND: ~4s; .ecxr ; kb SYMBOL_NAME: dumpdemo+1682 MODULE_NAME: dumpdemo IMAGE_NAME: dumpdemo.exe FAILURE_BUCKET_ID: NULL_POINTER_WRITE_c0000005_dumpdemo.exe!Unknown OS_VERSION: 10.0.26100.1 BUILDLAB_STR: ge_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {78a98d01-ecf2-dbb7-c5b9-5fb9cd0cc5e2} Followup: MachineOwner --------- 0:004> .ecxr rax=0000000000000000 rbx=0000019f92279e60 rcx=00000018c2d828f9 rdx=00000018ca1b2b0e rsi=00004e94914f0000 rdi=000009ac1b967bb8 rip=00007ff7b2f41682 rsp=00000084c57ff970 rbp=0000000000000000 r8=0000000000000083 r9=000000007ffe7000 r10=0000000000000001 r11=fffffffff8bcfdeb r12=0000000000000000 r13=0000000000000000 r14=b2f4fc0794908cf3 r15=0000000000000000 iopl=0 nv up ei pl zr na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 dumpdemo+0x1682: 00007ff7`b2f41682 c70021000000 mov dword ptr [rax],21h ds:00000000`00000000=???????? 0:004> kb *** Stack trace for last set context - .thread/.cxr resets it # RetAddr : Args to Child : Call Site 00 00007ff7`b2f4126b : 000009aa`f19089b8 0000019f`92279e60 00000000`00000000 00000000`00000000 : dumpdemo+0x1682 01 00007ffb`d31c37b0 : 0000019f`92275720 00000000`00000000 00000000`00000000 00000000`00000000 : dumpdemo+0x126b 02 00007ffb`d4a4e8d7 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ucrtbase!thread_start+0x30 03 00007ffb`d5b314fc : 00000000`00000000 00000000`00000000 000004f0`fffffb30 000004d0`fffffb30 : kernel32!BaseThreadInitThunk+0x17 04 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x2c