打开APP
未登录
开通VIP,畅享免费电子书等14项超值服
开通VIP
首页
好书
留言交流
下载APP
联系客服
Linux 获取并分析程序崩溃时的调用堆栈
昵称5169677
>《linux学习》
2016.08.14
关注
http://blog.csdn.net/zsf8701/article/details/8812508
下面是一个小例子,说明了程序出现段错误时,如何打印程序的堆栈信息。
[cpp]
view plain
copy
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <signal.h>
static
void
WidebrightSegvHandler(
int
signum)
{
void
*array[10];
size_t
size;
char
**strings;
size_t
i, j;
signal(signum, SIG_DFL);
/* 还原默认的信号处理handler */
size = backtrace (array, 10);
strings = (
char
**)backtrace_symbols (array, size);
fprintf(stderr,
"widebright received SIGSEGV! Stack trace:\n"
);
for
(i = 0; i < size; i++) {
fprintf(stderr,
"%d %s \n"
,i,strings[i]);
}
free (strings);
exit(1);
}
int
invalide_pointer_error(
char
* p)
{
*p =
'd'
;
//让这里出现一个访问非法指针的错误
return
0;
}
void
error_2(
char
* p)
{
invalide_pointer_error(p);
}
void
error_1(
char
* p)
{
error_2(p);
}
void
error_0(
char
* p)
{
error_1(p);
}
int
main()
{
//设置 信好的处理函数
signal(SIGSEGV, WidebrightSegvHandler);
// SIGSEGV 11 Core Invalid memory reference
signal(SIGABRT, WidebrightSegvHandler);
// SIGABRT 6 Core Abort signal from
char
*a = NULL;
error_0(a);
exit(0);
}
然后为了定位错误,我们需要加上-g参数编译一个带调试信息的版本,程序运行后打印堆栈信息如下
[cpp]
view plain
copy
widebright received SIGSEGV! Stack trace:
0 ./a.out [0x8048580]
1 [0xb7fb3400]
2 ./a.out [0x8048636]
3 ./a.out [0x8048649]
4 ./a.out [0x804865c]
5 ./a.out [0x80486a9]
6 /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5) [0xb7e52775]
7 ./a.out [0x80484c1]
知道了函数的地址可以有三种方法获取函数所在的文件和名称等相关信息。
使用GDB调试工具定位和调试错误。
info line *0x8048580 打印地址0x8048580处的相关信息。
list *0x8048580 获取地址0x8048580相关的上下文代码信息。
然后便可以确定行号,进行gdb调试了。
使用GCC编译选项生成MAP文件查找地址对应的函数信息。
使用GCC编译选项生成MAP文件查找地址对应的函数信息。在通过gcc/g++间接调用链接程序ld时,所有的ld选项前必须加上“-Wl,”,因为-Map是ld的选项。所以,要让g++生成mapfile,需要增加编译参数“ -Wl,-Map,mapfile”。
例:gcc -o helloworld helloworld.c -Wl,-Map,helloworld.map
然后通过map文件来查看函数的地址和函数名的对应关系了。
使用 Addr2line 将函数地址解析为函数名。
Addr2line 工具(它是标准的 GNU Binutils 中的一部分)是一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具。这种功能对于将跟踪地址转换成更有意义的内容来说简直是太棒了。
注意编译程序时需要添加-g选项才可以,也可以添加-Wl 和-map选项。
在调用 Addr2line 工具时,要使用 -e 选项来指定可执行映像是 test。通过使用 -f 选项,可以告诉工具输出函数名。
例如:addr2line 0x08048258 -e test -f
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报
。
打开APP,阅读全文并永久保存
查看更多类似文章
猜你喜欢
类似文章
c中如何打印函数调用堆栈?
第一时间捕获段错误(segment fault)的详细信息
巧用backtrace系列函数,在不具备gdb环境的Linux系统上大致定位...
Linux下的C语言编程(2)
关于GDB你需要知道的技巧
Segmentation fault
更多类似文章 >>
生活服务
热点新闻
留言交流
回顶部
联系我们
分享
收藏
点击这里,查看已保存的文章
导长图
关注
一键复制
下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!
联系客服
微信登录中...
请勿关闭此页面
先别划走!
送你5元优惠券,购买VIP限时立减!
5
元
优惠券
优惠券还有
10:00
过期
马上使用
×