C/C++打印堆栈信息
转自:http://www.cnblogs.com/zhurizhe/p/3412369.html
在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++打印堆栈信息的更多相关文章
- log4j打印堆栈信息
原文地址:https://blog.csdn.net/xianyu_0418/article/details/6043174 大家都知道,网站在运行的过程中,打印必要的log对记录网站的运行情况.从而 ...
- Lua调用C++时打印堆栈信息
公司的手游项目,使用的是基于cocos2d-x绑lua的解决方案(参数quick-x的绑定),虽然使用了lua进行开发,更新很爽了,但是崩溃依然较为严重,从后台查看崩溃日志时,基本上只能靠" ...
- 转:Xcode打印堆栈信息
2# 分享于 14-11-26 19:15:36 Chrome 39.0.2171.71 Mac OS X 10.10.1 如果只是看调用栈的话,可以使用 lldb 的功能.在你的代码里面打上一个 ...
- java Exception 出错的栈信息打印到日志中 打印堆栈信息
我们在开发程序的过程当中,日志是必不可少的工具,这有助于我们分析问题的原因,和出错的详细信息,而java的异常机制又会方便且迅速的帮我们找到出错行的位置. try { .... } catch (Ex ...
- python 打印堆栈信息方法
第一种方法使用logging模块 import logging def test(self): try: 1 / 0 # 触发异常 except BaseException as e: logging ...
- java打印堆栈信息
StackTraceElement[] stackElements = new Throwable().getStackTrace(); if(stackElements != null){ for( ...
- Logger.error方法之打印错误异常的详细堆栈信息
一.问题场景 使用Logger.error方法时只能打印出异常类型,无法打印出详细的堆栈信息,使得定位问题变得困难和不方便. 二.先放出结论 Logger类下有多个不同的error方法,根据传入参数的 ...
- log4j打印错误异常的详细堆栈信息
一.问题场景 使用Logger.error方法时只能打印出异常类型,无法打印出详细的堆栈信息,使得定位问题变得困难和不方便. 二.先放出结论 Logger类下有多个不同的error方法,根据传入参数的 ...
- logger.error打印完整的错误堆栈信息
使用Spring Boot项目中的日志打印功能的时候,发现调用Logger.errror()方法的时候不能完全地打印出网站的错误堆栈信息,只能打印出这个错误是一个什么错误. 为什么呢,原因在于这个方法 ...
随机推荐
- QEP之init()和dispatch()流程图
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键. 具体状 ...
- python 自定义函数表达式 拟合求系数
https://docs.scipy.org/doc/scipy/reference/tutorial/integrate.html https://docs.scipy.org/doc/scipy/ ...
- python中的__all__
在定义一个模块的时候,在开头处加上 “ __all__ = ["xxx1", "xxx2"] ”(xxx可以是方法.类.变量等希望让外界访问的值),那么在外部通 ...
- 【转载++】C/C++错误分析errno,perror,strerror和GetLastError()函数返回的错误代码的意义
本文是上一篇“fopen返回0(空指针NULL)且GetLastError是0”的侧面回应.听赶来多么地正确和不容置疑,返回NULL时调用GetLastError来看看报错啊,但当时却返回了0,大家都 ...
- linux线程篇 (三) 线程的同步
1 互斥量 pthreat_mutex_t mymutex; //1. 创建 初始化 int pthread_mutex_init(pthread_mutex_t *mutex, const pthr ...
- C++ STL lower_bound()和upper_bound()
lower_bound()和upper_bound()用法 1.在数组上的用法 假设a是一个递增数组,n是数组长度,则 lower_bound(a, a+n, x):返回数组a[0]~a[n-1]中, ...
- LeetCode初级算法的Python实现--链表
LeetCode初级算法的Python实现--链表 之前没有接触过Python编写的链表,所以这里记录一下思路.这里前面的代码是和leetcode中的一样,因为做题需要调用,所以下面会给出. 首先定义 ...
- C++三元操作符
c++的三元操作符形式: //条件表达式 ? 表达式1 : 表达式2; 语义:如果“条件表达式”为true,则整个表达式的值就是表达式1,忽略表达式2:如果“条件表达式”为false,则整个表达式的值 ...
- CSS3 子节点选择器
CSS3中新增了几个子元素选择器,大大提高了开发者的开发效率.之前有些要通过为一个个子元素添加class,或者js实现才能实现的效果.现在可以很方便的用选择器实现. 这些新的样式已被现代浏览器及IE9 ...
- `Facebook.Unity.Settings' has already been imported error solution
after import facebook sdk to unity, i get the '`Facebook.Unity.Settings' has already been imported' ...