我发现 Breakpad 有时无法处理 sigsegv。 我写了一个简单的例子来重现它:
#include <vector>
#include <breakpad/client/linux/handler/exception_handler.h>
int InitBreakpad()
{
char core_file_folder[] = "/tmp/cores/";
google_breakpad::MinidumpDescriptor descriptor(core_file_folder);
auto exception_handler_ =
new google_breakpad::ExceptionHandler(descriptor,
nullptr,
nullptr,
nullptr,
true,
-1);
}
int main()
{
InitBreakpad();
// int* ptr = nullptr;
// *ptr = 1;
std::vector<int> sum;
sum.push_back(1);
auto it = sum.begin();
sum.erase(it);
sum.erase(it);
return 0;
}
gcc 是 4.8.5,我的编译命令是
g++ test_breakpad.cpp -I./include -I./include/breakpad -L./lib -lbreakpad -lbreakpad_client -std=c++11 -lpthread
运行a.out,得到“Segmentation failure”,但没有生成minidump。
如果我取消注释 nullptr write,breakpad 就可以工作!
我应该怎么做才能纠正它?
GDB 调试输出:
(gdb) b google_breakpad::ExceptionHandler::~ExceptionHandler()
Breakpoint 2 at 0x402ed0: file src/client/linux/handler/exception_handler.cc, line 264.
(gdb) c
The program is not being run.
(gdb) r
Starting program: /home/zen/tmp/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Breakpoint 1, google_breakpad::ExceptionHandler::ExceptionHandler (this=0x619040, descriptor=..., filter=0x0, callback=0x0, callback_context=0x0, install_handler=true, server_fd=-1) at src/client/linux/handler/exception_handler.cc:224
224 ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7_3.1.x86_64 libgcc-4.8.5-11.el7.x86_64 libstdc++-4.8.5-11.el7.x86_64
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff712f19d in __memmove_ssse3_back () from /lib64/libc.so.6
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff712f19d in __memmove_ssse3_back () from /lib64/libc.so.6
(gdb) c
Continuing.
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
我尝试了进程转储之外的breakpad,但仍然一无所获(nullptr write 有效)。
最佳答案
经过一番调试,我认为 sum.erase(it)
的原因是在您的示例中未创建小型转储是由于堆栈损坏。
调试时可以看到变量 g_handler_stack_
在src/client/linux/handler/exception_handler.cc
已正确初始化并且 google_breakpad::ExceptionHandler
实例已正确添加到向量中。然而当 google_breakpad::ExceptionHandler::SignalHandler
被称为向量被报告为空,尽管没有调用 google_breakpad::ExceptionHandler::~ExceptionHandler
或 std::vector
中的任何一个改变向量的方法。
一些指向堆栈损坏的进一步数据点是代码与 clang++
一起工作。 。此外,一旦我们更改 std::vector<int> sum;
到 std::vector<int>* sum
,这将确保我们不会损坏堆栈,将小型转储写入磁盘。
关于minidump - Breakpad 不会在删除迭代器上生成小型转储两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45994833/