我正在Linux系统(内核2.6.23)上运行一个多线程C++程序。我的代码是使用G++版本4.7.4编译的。
我添加了以下代码来捕获分段错误:
void segFaultHandler(int sig)
{
void *array[10];
size_t size;
size = backtrace(array, 10);
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}在main上:
main()
{
signal(SIGSEGV, segFaultHandler);
try {
program code here...
catch(const std::exception& ex)
{
std::cerr << "Error occurred: " << ex.what() << std::endl;
}
catch(...)
{
std::cerr << "Unknown failure occurred. Possible memory corruption" << std::endl;
}
return 0;
}运行时,我的程序崩溃,输出如下:
Error: signal 11:
/home/cross/bin/aeirtu[0x807406e]
[0xffffe420]
/lib/libc.so.6(memcpy+0x2f)[0xb7d9bcbf]
/usr/gcc-4.7.4/lib/libstdc++.so.6(_ZNSt15basic_streambufIcSt11char_traitsIcEE6xsputnEPKci+0x73)[0xb7f26933]这不是一个容易的调试,因为我的程序只是偶尔崩溃,所以我需要一个工具来获取崩溃源并修复它。
从给定的输出中,我如何才能追溯导致崩溃的函数和代码?
发布于 2015-12-08 01:25:00
您可以使用valgrind来定位段故障的来源。如果你的二进制文件是用debug符号编译的,它会给你确切的源代码位置:
==12834== Invalid write of size 4
==12834== at 0x4004FD: main (test.cc:3)
==12834== Address 0x0 is not stack'd, malloc'd or (recently) free'd发布于 2018-03-27 00:50:51
您可以使用谷歌的Address Sanitizer (ASAN)来检测分段错误以及其他与内存相关的常见编程错误(包括释放后的堆使用、缓冲区溢出、缓冲区下溢、两次释放内存、内存泄漏等)。如果检测到错误,它将给出错误发生位置的堆栈跟踪(如果使用-g包含调试符号,堆栈跟踪是相当容易理解的)。
ASAN在编译时链接到您的二进制文件中,并在运行时检查您的堆,开销非常小(代码运行速度大约慢2倍)。这比valgrind快得多,并且它的优点是它可以在实时环境中运行,并且如果速度减慢2倍对于您的用例来说是可以接受的,那么它可以提供有价值的消息。
此外,如果您的分段错误是由上述编程错误之一引起的,则它将在代码甚至seg错误之前被ASAN捕获。例如,假设您的缓冲区溢出,破坏了堆的状态。当您稍后转到malloc内存时,malloc seg会出错,因为堆已损坏。任何信号处理程序都会在这一点上检测到损坏,即使真正的问题是堆缓冲区溢出。在堆缓冲区溢出时,ASAN会给你一个堆栈跟踪。
https://stackoverflow.com/questions/34139308
复制相似问题