我正在Linux系统中运行多线程C ++程序 (内核2.6.23)。我的代码是使用G ++ 4.7.4版编译的。
我添加了以下代码来捕获分段错误:
<variable name="StdLayout"
value="${longdate} | ${level} | ${logger} | ${message:exceptionSeparator= }${exception:format=tostring}" />
主要:
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()
{
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;
}
这不是一个简单的调试,因为我的程序有时会崩溃,所以我需要一个工具来获取崩溃源并修复它。
从给定的输出中,我如何追溯导致崩溃的函数和代码段?
答案 0 :(得分:3)
您可以使用valgrind找到段错误的来源。如果您使用调试符号编译二进制文件,它将为您提供确切的源位置:
==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
答案 1 :(得分:0)
您可以使用谷歌的Address Sanitizer (ASAN)来检测分段错误以及与内存相关的其他常见编程错误(包括释放后的堆使用,缓冲区溢出,缓冲区下溢,释放内存两次,内存泄漏等)。如果检测到错误,它将给出错误发生位置的堆栈跟踪(如果使用-g包含调试符号,则堆栈跟踪可以理解)。
ASAN在编译时链接到您的二进制文件,并在运行时以非常小的开销检查您的堆(代码运行速度慢约2倍)。这比valgrind快得多,并且具有以下优势:它可以在实时环境中运行,并且如果您的用例可以接受2x减速,则会提供有价值的消息。
此外,如果您的分段错误是由上述编程错误之一引起的,那么在代码甚至出现错误之前,它将被ASAN捕获。例如,假设您缓冲溢出,破坏堆的状态。当您稍后转到malloc内存时,malloc seg会因为堆已损坏而出错。即使真正的问题是堆缓冲区溢出,任何信号处理程序都会在此时检测到损坏。 ASAN会在堆缓冲区溢出时为您提供堆栈跟踪。