嵌入式开发环境下,用gdb调试coredump的问题可能是件麻烦事。用 backtrace() 和 backtrace_symbols() 可以获取当前线程的调用栈的信息,可以快捷定位coredump的位置。
1. 打印调用栈
1.1 backtrace()
backtrace() 向数组buffer写入当前调用栈中每个栈帧的返回地址。100是buffer的大小,返回值nptrs是返回栈帧的个数。如果buffer不够大,则返回最近的帧。
void *buffer[100];
int nptrs = backtrace (buffer, 100);
1.2 backtrace_symbols()
backtrace_symbols() 将 backtrace() 返回的地址数组,转换成字符串形式的符号信息。返回值strings是char*类型的数组,由backtrace_symbols()调用malloc()分配,调用者需要释放strings(但不需要释放数组中的字符串)。
char** strings = backtrace_symbols (buffer, nptrs);
for (int i = 0; i < nptrs; i++)
printf ("%s\n", strings[i]);
与backtrace_symbols()类似的,还有backtrace_symbols_fd()。不同的是,它将符号信息的字符串写入fd指定的文件中,每个字符串一行。
2. 捕捉信号
可以捕捉常见的错误导致的信号,在信号处理函数中打印调用栈。如下代码的信号处理函数是signalProc()。
void signalProc (int sig, siginfo_t* info, void* ptr)
{
printf ("catch signal: %d\n", sig);
// call backtrace() and backtrace_symbols() as above
signal (sig, SIG_DFL);
raise (sig);
}
void init (void)
{
struct sigaction action;
memset (&action, 0, sizeof(action));
action.sa_sigaction = signalProc;
action.sa_flags = SA_SIGINFO;
sigaction (SIGSEGV, &action, NULL);
}
3. 分析Coredump的源代码位置
运行程序让它Coredump,得到如下打印信息。可以看到崩溃的位置是0x1bd60。
========================================
catch signal: 11
si_signo = 11(SIGSEGV)
...
/lib/libc.so.6(+0x25040) [0xb53a6040]
./player(_ZN9PlayerEnd4initEv+0x178) [0x1bd60]
./player(_ZN9PlayerApp5startEv+0x40) [0x1a5e8]
/extp/pos/lib/libappfrm.so(_ZN6AppFrm3runEiPPc+0x88) [0xb57caf0c]
./player(main+0x34) [0x1a524]
/lib/libc.so.6(__libc_start_main+0x9d) [0xb5397776]
========================================
用addr2line 得到 0x1bd60对应的源代码位置,在函数PlayerEnd::init()中,文件PlayerEnd.cpp的第34行。
percherry@ubuntu:~/dev/pos_db$ arm-linux-gnueabi-addr2line -e apps/player/src/player -f -C 0x1bd60
PlayerEnd::init()
/home/percherry/dev/pos/apps/player/src/PlayerEnd.cpp:34
相关链接
GDB 常用法
GDB 调试Coredump问题
嵌入式开发中GDB调试Coredump问题
嵌入式开发中GDB串口远程调试
用backtrace()调试coredump问题
Valgrind memcheck 用法
Address Sanitizer 用法
参考资料
根据backtrace_symbols查错误代码行号
https://blog.csdn.net/download_73/article/details/75433589
网友评论