addr2line有什么作用呢? 可别小瞧它, 它可以定位到代码出错的位置。 下面, 我们来看看这个简单的代码:
#include <stdio.h>
int main()
{
int *p = NULL;
*p = 0;
printf("bad\n");
return 0;
}
这个程序很小, 我们可以一眼就看出程序在运行期出错。 但是, 如果是大程序, 在运行期出错, 我们该如何定位呢? 那就必须依赖于工具, 而不是你我的肉眼。
我们以上述小程序为例, 进行如下操作:
[taoge@localhost learn_c]$ gcc -o taogeSeg -g taogeSeg.c
[taoge@localhost learn_c]$ ./taogeSeg
Segmentation fault (core dumped)
[taoge@localhost learn_c]$ dmesg | grep taogeSeg
taogeSeg[4941]: segfault at 0 ip 080483c9 sp bfb92410 error 6 in taogeSeg[8048000+1000]
[taoge@localhost learn_c]$ addr2line -e taogeSeg 080483c9
/home/taoge/Desktop/learn_c/taogeSeg.c:6
[taoge@localhost learn_c]$ cat -n taogeSeg.c
1 #include <stdio.h>
2
3 int main()
4 {
5 int *p = NULL;
6 *p = 0;
7
8 printf("bad\n");
9 return 0;
10 }
[taoge@localhost learn_c]$
我来解释一下:
1. gcc -o taogeSeg -g taogeSeg.c :生成带有调试信息的可执行文件taogeSeg
2. dmesg | grep taogeSeg :获得执行taogeSeg后的出错信息, 你可以将结果理解为日志, 其中的080483c9是一个地址, 正是这个地址出错了
3. addr2line -e taogeSeg 080483c9 :将出错地址转换成源代码对应的行, 结果为6, 也就是说源代码第6行有问题。 一看, 果然是,
万恶的*p=0;被揪出来了。
当然, 针对这个例子, 会gdb调试的朋友肯定也能调试出来,而且也确实能找到代码出错的地址和源代码行, 从这个意义上来讲, gdb内部也携带了类addr2line的功能。这是不是说gdb就可以替代addr2line呢? 不是的。 如果某bug低概率发生, 现在只有一份crash log, 那就要用addr2line了, 因为你用gdb时, 该bug不一定发生啊。
实际上, 在很多linux大型软件开发中, 经常出现段错误, 造成进程挂掉, 系统崩溃等问题, 此时, 用addr2line是比较好的方法。在后面的博文中, 我们会继续了解与addr2line有关的调试方法, 毕竟, 代码调试太重要了。其实呢, 如果不熟悉addr2line的使用, 或者干脆没有听说过这个命令, 那最好不要说自己搞linux开发, 免得被人鄙视啊。
OK, 本文只是一个引子, 能在实战中熟练使用addr2line才见真功夫。如能熟练掌握addr2line的使用, 以后听到什么段错误, 系统崩溃, 就没那么毛骨悚然了。