Google Breakpad在LLDB调试环境初始化时崩溃问题排查
问题:LLDB调试环境下初始化Google Breakpad崩溃,Shell运行正常
系统环境:MacOS 13(Ventura),开发IDE:Visual Studio Code
调用以下代码中的init()函数时程序崩溃,但脱离LLDB调试器在Shell中运行完全正常:
namespace crashhandler { static std::unique_ptr<google_breakpad::ExceptionHandler> pExceptionHandler; namespace { bool DumpCallback(const char* dump_dir, const char* minidump_id, void*, bool success) { if (success) printf("Application crashed. Breakpad Crash Handler created a dump at location %s/%s.dmp\n", dump_dir, minidump_id); else printf("Application crashed. Breakpad Crash Handler failed to create a dump"); fflush(stdout); return success; } } // namespace void init(const std::string& reportPath) // <-- 调用此函数时崩溃 { if (pExceptionHandler) return; pExceptionHandler.reset( new google_breakpad::ExceptionHandler(reportPath, nullptr, DumpCallback, nullptr, true, nullptr)); } } // namespace crashhandler
调试控制台输出错误信息:
================================================================= ==5060==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x00016fdfee00 at pc 0x000100ac9030 bp 0x00016ff11540 sp 0x00016ff10d08 READ of size 4608 at 0x00016fdfee00 thread T2 #0 0x100ac902c in wrap_write+0x15c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1902c) #1 0x100109f08 in google_breakpad::UntypedMDRVA::Copy(unsigned int, void const*, unsigned long)+0x54 (my_server:arm64+0x100109f08) #2 0x10010ce14 in google_breakpad::MinidumpGenerator::WriteStackFromStartAddress(unsigned long long, MDMemoryDescriptor*)+0xf8 (my_server:arm64+0x10010ce14) #3 0x10010d244 in google_breakpad::MinidumpGenerator::WriteThreadStream(unsigned int, MDRawThread*)+0x100 (my_server:arm64+0x10010d244) #4 0x10010c04c in google_breakpad::MinidumpGenerator::WriteThreadListStream(MDRawDirectory*)+0xfc (my_server:arm64+0x10010c04c) #5 0x10010bd20 in google_breakpad::MinidumpGenerator::Write(char const*)+0xc8 (my_server:arm64+0x10010bd20) #6 0x10010adc0 in google_breakpad::ExceptionHandler::WriteMinidumpWithException(int, int, int, __darwin_ucontext64*, unsigned int, bool, bool)+0x160 (my_server:arm64+0x10010adc0) #7 0x10010af1c in google_breakpad::ExceptionHandler::WaitForMessage(void*)+0x104 (my_server:arm64+0x10010af1c) #8 0x1a330a068 in _pthread_start+0x90 (libsystem_pthread.dylib:arm64e+0x7068) #9 0x1a3304e28 in thread_start+0x4 (libsystem_pthread.dylib:arm64e+0x1e28) Address 0x00016fdfee00 is located in stack of thread T0 at offset 0 in frame #0 0x1000034cc in main main.cpp:36 This frame has 10 object(s): [32, 56) 'reportPath' (line 39) <== Memory access at offset 0 partially underflows this variable [96, 120) 'ref.tmp' (line 40) <== Memory access at offset 0 partially underflows this variable [160, 208) 'parser' (line 43) <== Memory access at offset 0 partially underflows this variable [240, 264) 'configPath' (line 45) <== Memory access at offset 0 partially underflows this variable [304, 320) 'ref.tmp12' (line 46) <== Memory access at offset 0 partially underflows this variable [336, 360) 'agg.tmp' <== Memory access at offset 0 partially underflows this variable [400, 416) 'ref.tmp30' (line 57) <== Memory access at offset 0 partially underflows this variable [432, 456) 'agg.tmp42' <== Memory access at offset 0 partially underflows this variable [496, 520) 'agg.tmp80' <== Memory access at offset 0 partially underflows this variable [560, 568) 'ref.tmp86' (line 74) <== Memory access at offset 0 partially underflows this variable HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-underflow (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1902c) in wrap_write+0x15c Shadow bytes around the buggy address: 0x00702dfdfd70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00702dfdfd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00702dfdfd90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00702dfdfda0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00702dfdfdb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x00702dfdfdc0:[f1]f1 f1 f1 00 00 00 f2 f2 f2 f2 f2 f8 f8 f8 f2 0x00702dfdfdd0: f2 f2 f2 f2 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 0x00702dfdfde0: f8 f2 f2 f2 f2 f2 f8 f8 f2 f2 00 00 00 f2 f2 f2 0x00702dfdfdf0: f2 f2 f8 f8 f2 f2 00 00 00 f2 f2 f2 f2 f2 00 00 0x00702dfdfe00: 00 f2 f2 f2 f2 f2 f8 f3 f3 f3 f3 f3 00 00 00 00 0x00702dfdfe10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Thread T2 created by T0 here: #0 0x100ae8c5c in wrap_pthread_create+0x54 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x38c5c) #1 0x10010a360 in google_breakpad::ExceptionHandler::Setup(bool)+0xd0 (my_server:arm64+0x10010a360) #2 0x10010a1c4 in google_breakpad::ExceptionHandler::ExceptionHandler(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool (*)(void*), bool (*)(char const*, char const*, void*, bool), void*, bool, char const*)+0x110 (my_server:arm64+0x10010a1c4) #3 0x1001132b4 in crashhandler::init(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)+0x58 (my_server:arm64+0x1001132b4) #4 0x10000367c in main main.cpp:41 #5 0x1a2fdfe4c (<unknown module>) ==5060==ABORTING
问题原因
这是AddressSanitizer(ASan)与LLDB调试环境的栈内存检测冲突导致的假阳性报错,具体细节:
- Breakpad初始化时会创建后台监控线程(日志中的T2),该线程会读取主线程(T0)的栈内存,用于后续生成崩溃minidump文件。
- 在LLDB调试模式下,ASan会对栈内存添加特殊标记(比如栈左红区标记为
f1),Breakpad读取栈内存的操作会触发ASan的检测逻辑,被误判为栈缓冲区下溢。 - 脱离LLDB调试器时,ASan的栈内存标记逻辑或Breakpad的栈读取行为不受调试器环境干扰,因此不会触发报错。
错误日志中的HINT也明确提示:如果程序使用自定义栈展开机制(Breakpad的minidump生成就属于这类场景),可能会出现此类假阳性,而longjmp和C++异常是ASan支持的合法场景。
内容的提问来源于stack exchange,提问作者Alex O
相关产品推荐
相关产品推荐

