在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 ...
随机推荐
- js继承的几种方法和es6继承方法
一.原型链继 1.基本思想 利用原型链来实现继承,超类的一个实例作为子类的原型 2.具体实现 function F() {} //原型属性,原型方法: ...
- Jenkins 添加节点 java web方式
环境说明: 主节点:windows server 从节点:两台linux 1. windows server安装jenkins就不多说了,直接添加节点配置如下 2.全局安全配置,指定确认的端口后,记得 ...
- Vue2+VueRouter2+webpack+vue-cil构建完整项目实例(附:详细步骤截图)
引用1:https://segmentfault.com/a/1190000008557578 引用2:https://blog.csdn.net/wulala_hei/article/details ...
- php GD 圆图 -处理成圆图片
<?php /** * 处理成圆图片,如果图片不是正方形就取最小边的圆半径,从左边开始剪切成圆形 * @param string $imgpath [description] * @return ...
- STM32CubeMx配置正交编码器遇到的问题
配置时参考了这个哥们的方法: http://www.eemaker.com/stm32cubemx-encoder.html 然后我的配置是这样的 配置是没有问题. 调用时出现了问题. 由于配置完了, ...
- python mac下安装虚拟环境
Mac 下 Flask 框架 workon命令找不到 ---- 最终解决方案(详解具体实现操作过程中遇到的坑) Mac 下 Flask 的 全网最详细搭建 1.安装virtualenv和virtual ...
- My First Marathon【我的第一次马拉松】
My First Marathon A month before my first matathon, one of my ankles was injured and this meant not ...
- 学会了 python 的pip方法安装第三方库
超级开心啊!!!!!!!!!!!!! win10 打开cmd Installing with get-pip.py To install pip, securely download get-pip. ...
- 大数据培训班 cloudera公司讲师面对面授课 CCDH CCAH CCP
大数据助力成就非凡.大数据正在改变着商业游戏规则,为企业解决传统业务问题带来变革的机遇.毫无疑问,当未来企业尝试分析现有海量信息以推动业务价值增值时,必定会采用大数据技术. 目前对大数据的分析工具,首 ...
- Encrypted bootloader (程序BIN文件加密及在线升级)
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 在上一个博客随笔,我介 ...