backtrace() 段错误定位
段错误定位
原因是昨天遇到一个BUG,复现概率很小,一直复现了一下午,后来google发现可以用execinfo.h里的backtrace函数及信号处理机制, 来让程序在发生段错误时自动打印调用堆栈。最后终于复现出来了两次,用这个函数也定位到了出错位置,是多线程下的一个同步问题。
之前遇到的BUG基本都是可复现的,用简单的打印很快就能定位到BUG位置。对于这种不可复现的BUG在开发测试的时候最好能一直带着backtrace函数,以最快的速度定位BUG。
#include <execinfo.h>
#define BACKTRACE_SIZE 256
void segv_handler(int sig)
{
void *func[BACKTRACE_SIZE];
int size;
size = backtrace(func, BACKTRACE_SIZE);
backtrace_symbols_fd(func, size, STDERR_FILENO);
exit(1);
}
int main(void)
{
int *p = NULL;
signal(SIGSEGV, segv_handler);
*p = 0xdeadbeef; //---------------------Line 29
return 0;
}
程序开始的时候注册一下SIGSEGV信号的回调,然后编译的时候带上-g。程序运行出错的时候会以汇编的形似打印调用栈。形式一般是这样:
./auto[0x400654]
/lib64/libc.so.6(+0x35250)[0x7fbbe4283250]
./auto[0x400543] //----------------出错地址
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fbbe426fb35]
./auto[0x40057e]
前边两行是SIGSEGV信号被触发的回调,第三行是段错误的位置。addr2line -e auto 0x400543
可以打印出这个地址对应的代码位置。或者也可以用objdump -d xxx
打印出来汇编然后去搜索这个地址。
PS:还有两个内存调试工具 valgrind检查内存泄漏; electric fence检查非法地址访问。
参考:https://www.cnblogs.com/lchzd8/p/15845824.html