一起talk C栗子吧(第一百二十五回:C语言实例--显示文件名和行号)
来源:互联网 发布:农村淘宝续签签署协议 编辑:程序博客网 时间:2024/04/30 12:12
各位看官们,大家好,上一回中咱们说的内置宏的例子,这一回咱们说的例子是:显示文件名和行号。闲话休提,言归正转。让我们一起talk C栗子吧!
我们在上一回中通过内置宏来显示文件名和行号。这一回,我们介绍另外一个显示文件名和行号的方法:使用addr2line这个工具来显示文件名行号。
addr2line是一个调试工具,主要借助可执行文件中的调试信息,把某个地址转换为程序中的文件名或者行号。该工具有多个选项,我们常用的选项是”e”和”f”。
- 例如:addr2line -e a.out 0x12345678 会显示与0x12345678这个地址相对应的文件名和行号。
- 例如:addr2line -f -e a.out 0x12345678 会在原来的基础上显示与0x12345678这个地址相对应的函数名,当然了这两个选项可以一起使用,这样就可以同时显示文件名,函数名和行号。
看官们,光说不练不是我们的风格,我们举一个实际的例子,通过代码来说明如何使用addr2line这个工具来显示文件名和行号。
在例子中,我们首先运行func函数,然后在主函数中显示函数func的地址。
int main(){ func(); printf("address of func:%p \n",func); return 0;}
函数func的定义如下,简单起见,我们只在该函数中输出一行语句,表示函数中运行。
void func(){ printf("func is running \n");}
我们编译该程序,并且加入调试信息,具体的命令如下:
gcc -g Ex082_addr2line.c -o s //编译生成名叫s的可执行文件
运行该文件,可以得到以下结果:
./s //运行该可执行文件func is running address of func:0x804844d //显示了函数的地址
接着我们通过地址来查看文件名,行号和函数名,具体的命令如下:
addr2line -f -e s 0x804844d //同时使用f和e选项,注意f需要基于e来运行,所以f在e前面func //显示与地址0x804844d对应的函数名/home/talk8/Ex082_addr2line.c:8 //显示与地址0x804844d对应的文件名和行号
看官们,正文中就不写代码了,完成的代码放到了我的资源中,大家可以点击这里下载使用。从代码中可
以看到func函数位于文件中的第8行。
最后我们来对比一下这两种显示文件名和行号方法的优缺点:
- 内置宏的优点:在程序运行时就能直接显示出文件名和行号,不需要调试和其它第三方工具。
- 内置宏的缺点:需要在运行的程序中提前加入内置宏,否则不会显示文件名和行号,此外,在程序中的哪 一行添加内置宏也是头疼的事情,这个需要依据程序的需要来添加。
- addr2line工具的优点:在调试程序的时候,通过某个地址直接显示文件名和行号(地址通常在dump文 件获取),最重要的是我们不需要在代码中添加任何内容。
- addr2line工具的缺点:需要在编译时使用gcc的”g”选项来加入调试信息,这会增加编译时间并且使目标文件的变大。此外,它需要使用程序中的地址才能显示文件名和行号,如果没有一个有效的地址,那么 它就无能为力了,正所谓巧妇难为无米之炊嘛。
依据我的经验来看,显示文件名和行号主要是为快速找出程序中的错误。如果程序中的错误比较容易重现,那么可以在程序中必要的地方提前加入内置宏,然后编译,并且运行编译后的程序。当重现错误时就会直接输出文件名和行号。这样就能快速定位到错误发生的文件和错误在文件中的位置。反之,如果程序中的错误不容易重现,那么就可以使用addr2line这个工具了。当程序发生错误时,生成dump文件(杧核心转储文件),在该文件中找到错误发生时的地址,使用该工具就可以得到发生错误的文件和错误在文件中的具体位置。另外,如果没有dump文件时,可以使用gdb进行调试,然后借助gdb的info命令查看相关函数的地址(该内容,我们在一百二十三回中介绍过,如果忘记了,可以点击这里查看前面章回的内容)。
看官们,在实际工作中,我们写的程序会发生各种各样的错误。因此,希望大能够自己动手熟练掌握这两种显示文件名和行号的方法 。并且结合我分享的经验在不同的情况中使用不同的方法,快速地找出程序中的错误。
各位看官,关于显示文件名和行号的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。
- 一起talk C栗子吧(第一百二十五回:C语言实例--显示文件名和行号)
- 一起talk C栗子吧(第一百二十三回:C语言实例--显示变量和函数的地址)
- 一起talk C栗子吧(第一百二十回:C语言实例--线程属性)
- 一起talk C栗子吧(第一百二十四回:C语言实例--内置宏)
- 一起talk C栗子吧(第一百二十六回:C语言实例--static关键字)
- 一起talk C栗子吧(第一百二十二回:C语言实例--多线程)
- 一起talk C栗子吧(第一百二十九回:C语言实例--C程序内存布局一)
- 一起talk C栗子吧(第一百二十七回:C语言实例--查看main函数的参数)
- 一起talk C栗子吧(第一百二十八回:C语言实例--查看当前进程信息)
- 一起talk C栗子吧(第一百二十一回:C语言实例--线程知识体系图)
- 一起talk C栗子吧(第一百一十五回:C语言实例--线程同步之互斥量一)
- 一起talk C栗子吧(第二十五回:C语言实例--二分查找)
- 一起talk C栗子吧(第三十五回:C语言实例--测试程序运行时间)
- 一起talk C栗子吧(第四十五回:C语言实例--深度优先遍历二)
- 一起talk C栗子吧(第六十五回:C语言实例--DIY字符串连接函数)
- 一起talk C栗子吧(第七十五回:C语言实例--DIY ls命令)
- 一起talk C栗子吧(第一百一十回:C语言实例--线程标识符)
- 一起talk C栗子吧(第一百一十七回:C语言实例--线程死锁一)
- PHP之前端控制器
- 二叉树树形输出的几种方法
- Java开发编程基础-1
- [UnityShader2]顶点片段着色器基础
- 剑指offer面试题之替换空格
- 一起talk C栗子吧(第一百二十五回:C语言实例--显示文件名和行号)
- HBase源码分析之事件处理模型
- Mysql常用表管理语句
- 与一线Linux嵌入式开发工程师的对话
- 双向冒泡排序
- (8)ICE服务之网格计算模型
- Meanshift算法学习笔记
- {leetCode}2。addTwoNum
- C#中使用TeeChart控件出现 不支持无窗口的Active控件 的解决方法