在C/C++程序中打印当前函数调用栈
前几天帮同事跟踪的一个程序莫名退出,没有core dump(当然ulimit是打开的)的问题。我们知道,正常情况下,如果程序因为某种异常条件退出的话,应该会产生core dump,而如果程序正常退出的话,应该是直接或者间接的调用了exit()相关的函数。基于这个事实,我想到了这样一个办法,在程序开始时,通过系统提供的atexit(),向系统注册一个回调函数,在程序调用exit()退出的时候,这个回调函数就会被调用,然后我们在回调函数中打印出当前的函数调用栈,由此便可以知道exit()是在哪里调用,从而上述问题便迎刃而解了。上述方法用来解决类似问题是非常行之有效的。在上面,我提到了在“回调函数中打印出当前的函数调用栈”,相信细心的朋友应该注意到这个了,本文的主要内容就是详细介绍,如何在程序中打印中当前的函数调用栈。
我之前写过一篇题目为《介绍几个关于C/C++程序调试的函数》的文章,看到这里,请读者朋友先看一下前面这篇,因为本文是以前面这篇文章为基础的。我正是用了backtrace()和backtrace_symbols()这两个函数实现的,下面是一个简单的例子,通过这个例子我们来介绍具体的方法:
1 |
#include <execinfo .h> |
(说明:下面的介绍采用的环境是ubuntu 11.04, x86_64, gcc-4.5.2)
- 1. 通过下面的方式编译运行:
1 |
wuzesheng@ubuntu:~/work/test$ gcc test.cc -o test1 |
从上面的运行结果中,我们的确看到了函数的调用栈,但是都是16进制的地址,会有点小小的不爽。当然我们可以通过反汇编得到每个地址对应的函数,但这个还是有点麻烦了。不急,且听我慢慢道来,看第2步。
- 2. 通过下面的方式编译运行:
1 |
wuzesheng@ubuntu:~/work/test$ gcc test.cc -rdynamic -o test2 |
这下终于可以看到函数的名字了,对比一下2和1的编译过程,2比1多了一个-rdynamic的选项,让我们来看看这个选项是干什么的(来自gcc mannual的说明):
1 |
-rdynamic |
从上面的说明可以看出,它的主要作用是让链接器把所有的符号都加入到动态符号表中,这下明白了吧。不过这里还有一个问题,这里的函数名都是mangle过的,需要demangle才能看到原始的函数。关于c++的mangle/demangle机制,不了解的朋友可以在搜索引擎上搜一下,我这里就不多就介绍了。这里介绍如何用命令来demangle,通过c++filt命令便可以:
1 |
wuzesheng@ubuntu:~/work/test$ c++filt < << "_Z16print_stacktracev" |
写到这里,大部分工作就ok了。不过不知道大家有没有想过这样一个问题,同一个函数可以在代码中多个地方调用,如果我们只是知道函数,而不知道在哪里调用的,有时候还是不够方便,bingo,这个也是有办法的,可以通过address2line命令来完成,我们用第2步中编译出来的test2来做实验(address2line的-f选项可以打出函数名, -C选项也可以demangle):
1 |
wuzesheng@ubuntu:~/work/test$ addr2line -a 0x4008a7 -e test2 -f |
Oh no,怎么打出来的位置信息是乱码呢?不急,且看我们的第3步。
- 3. 通过下面的方式编译运行:
1 |
wuzesheng@ubuntu:~/work/test$ gcc test.cc -rdynamic -g -o test3 |
看上面的结果,我们不仅得到了调用栈,而且可以得到每个函数的名字,以及被调用的位置,大功告成。在这里需要说明一下的是,第3步比第2步多了一个-g选项,-g选项的主要作用是生成调试信息,位置信息就属于调试信息的范畴,经常用gdb的朋友相信不会对这个选项感到陌生。
在C/C++程序中打印当前函数调用栈的更多相关文章
- scala如何在任意方法中打印当前线程栈信息(StackTrace)
1.以wordcount为例 package org.apache.spark.examples import org.apache.spark.{SparkConf, SparkContext} / ...
- 程序中打印当前进程的调用堆栈(backtrace)
为了方便调式程序,产品中需要在程序崩溃或遇到问题时打印出当前的调用堆栈.由于是基于Linux的ARM嵌入式系统,没有足够的空间来存放coredump文件. 实现方法,首先用__builtin_fram ...
- 如何在linux用户空间程序中打印时间戳?
1. 使用clock_gettime接口即可 2. clock_gettime的使用方法: 2.1 定义一个结构体 struct timespec ts; 2.2 调用clock_gettime获取当 ...
- RDIFramework.NET ━ Web中打印的各种方案参考-欢迎补充
RDIFramework.NET ━ Web中打印的各种方案参考-欢迎补充 做Web开发的同志应该都深有体会,在web程序中打印不再象应用程序中那样便于控制了,web程序天生的一些特性造成了这个缺点, ...
- 程序中使用7-zip(7z)压缩文件
Email:longsu2010 at yeah dot net 工作中难免遇到需要压缩文件的情况,比如有一千万个小文件,每个文件约100k,如果使用7-zip压缩后可能十几k,可以节省很多磁盘空间. ...
- java中的堆、栈、常量池
java中的堆.栈.常量池 分类: java2010-01-15 03:03 4248人阅读 评论(5) 收藏 举报 javastring编译器jvm存储equals Java内存分配: 1. 寄存器 ...
- 在linux代码中打印函数调用的堆栈的方法
之前一直有这样的需求,当时问到,也没搜到方法,现在竟然既问到了,也搜到了,哎,世事真是不能强求啊! 在Linux内核调试中,经常用到的打印函数调用堆栈的方法非常简单,只需在需要查看堆栈的函数中加入: ...
- 在DevExpress程序中使用条形码二维码控件,以及进行报表打印处理
在很多业务系统里面,越来越多涉及到条形码.二维码的应用了,不管在Web界面还是WInform界面都需要处理很多物料相关的操作,甚至很多企业为了减少录入错误操作,为每个设备进行条形码.二维码的标签,直接 ...
- Android 中调试手段 打印函数调用栈信息
下面来简单介绍下 android 中的一种调试方法. 在 android 的 app 开发与调试中,经常需要用到打 Log 的方式来查看函数调用点. 这里介绍一种方法来打印当前栈中的函数调用关系 St ...
随机推荐
- <<学会提问>>第一章学习笔记
中国应不应该现在取消死刑? 中医是不是伪科学? 读书无用论? 集体主义和团队精神? 欧洲难民危机,你是支持接收难民,还是反对? 欧洲白左是不是幼稚圣母,抑或是右派种族歧视,顽固保守? 如何看待&quo ...
- VMware虚拟化NSX-Manager命令行更改admin用户密码
1.1 登录到NSX-Manager命令行界面,输入用户名和密码登录到用户模式 Log in to the vSphere Client and select an NSX virtual ap ...
- Cacti 学习笔记
Cacti是用php语言实现的一个软件,它的主要功能是用snmp服务获取数据,然后用rrdtool储存和更新数据,当用户需要查看数据的时候用rrdtool生成图表呈现给用户.因此,snmp和rrdto ...
- [原]解决phpstudy下的nginx无法运行的问题
一直在用phpstudy下的apache,今天忽然想切换到nginx,出现了一些错误,最终还是解决了. 之前是php 5.3 + apache 现在是php 5.3n + nginx 问题就出在这n上 ...
- CentOS下安装pip
CentOS下安装pip 通常情况下使用命令: yum -y install pip 也有可能报错,无法安装.这是应该使用第二种方法. 1.首先需要先安装扩展源EPEL: yum -y install ...
- UVA - 1606 Amphiphilic Carbon Molecules 极角扫描法
题目:点击查看题目 思路:这道题的解决思路是极角扫描法.极角扫描法的思想主要是先选择一个点作为基准点,然后求出各点对于该点的相对坐标,同时求出该坐标系下的极角,按照极角对点进行排序.然后选取点与基准点 ...
- grunt in webstorm
1.install grunt sudo npm install -g grunt-cli npm install grunt --save-dev
- List中的FindAll用法
在泛型List中查找符合某个字段的全部数据,可以采用如下方式: //1.现将实体数据listList<ADDaAn> objDAList = db.ADDaAns.ToList(); // ...
- SQL Server中2008及以上 ldf 文件过大的解决方法
在SQL Server中经常遇到事务日志变大的情况,除了将数据库设置为“自动收缩”外,还可以使用下面的SQL命令进行快速清除数据库中的事务日志,命令如下: - 第一步:清空日志 ALTER DAT ...
- Office Web Apps Server(1)
Office Web Apps Server runs on one or more servers and provides browser-based Office file viewi ...