Linux下追踪函数调用,打印栈帧
事情的起因是这样的,之前同事的代码有一个内存池出现了没有回收的情况。也就是是Pop出来的对象没有Push回去,情况很难复现,所以在Pop里的打印日志,跟踪是谁调用了它,我想在GDB调试里可以追踪调用的栈帧,那也一定有方法实现。首先上网搜索了一下,并没有结果!还好代码量不是很多,只能用最笨的方法,在每个调用Pop的地方,传参,把调用的文件,行号作为字符串传进去,在日志里打印!忙活完了,总感觉一定是有方法可以实现查看调用栈帧的,于是在QQ群里的问了下,果然有这方面经验的同学给出了答案!
主要是通过backtrace返回调用的栈帧,然后通过backtrace_symbols把地址转换为字符串。最后,在Linux下有个工具addr2line可以将地址转换为文件名和行号!通过管道调用addr2line,最后打印调用栈帧。
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* 打印栈帧
*
* 通过backtrace,backtrace_symbols获取栈帧信息,然后建立管道,通过addr2line解析
*
*/ int32_t myexec(const char *cmd)
{
FILE *pp = popen(cmd, "r"); //建立管道
if (!pp)
{
return -;
}
char tmp[];
while (fgets(tmp, sizeof(tmp), pp) != NULL)
{
if (tmp[strlen(tmp) - ] == '\n')
{
tmp[strlen(tmp) - ] = '\0'; //去除换行符
} printf("%-30s",tmp);
}
printf("\n");
pclose(pp); //关闭管道
return ;
} void parseName(char * str,char *exeName,char *addr)
{
char *strTemp = str;
char * addrTemp;
while (*strTemp)
{
if (*strTemp == '(')
memcpy(exeName, str, strTemp - str); if (*strTemp == '[')
addrTemp = strTemp; if (*strTemp == ']')
memcpy(addr, str + (addrTemp - str) + , strTemp - addrTemp - );
strTemp++;
}
} void print_trace(void)
{
void *array[];
size_t size;
char **strings; size = backtrace(array,);
strings = backtrace_symbols(array,size); printf("Obtained %zd stack frames.\n",size);
char cmd[] = {};
char exeName[] = {};
char addr[] = {};
for(size_t i = ;i < size;i++)
{
memset(cmd,,sizeof(cmd));
memset(exeName,,sizeof(exeName));
memset(addr,,sizeof(addr)); parseName(strings[i],exeName,addr);
printf("%-15s",addr);
sprintf(cmd,"addr2line -f -e %s %s",exeName,addr);
myexec(cmd);
}
} void dummp_function(void)
{
print_trace();
} int main(int argc,char *argv[])
{
dummp_function();
return ;
}
编译:
g++ -Wall -g backtrace.cpp -o bt
执行:
./bt
效果:
Obtained stack frames.
0x4009e6 _Z11print_tracev /home/dyf/Project/Tool/backtrace.cpp:
0x400b71 _Z14dummp_functionv /home/dyf/Project/Tool/backtrace.cpp:
0x400b87 main /home/dyf/Project/Tool/backtrace.cpp:
0x7fa51f761af5 __libc_start_main ??:
0x400769 _start ??:0
大致满足自己的需求效果,函数名称还需要修饰一下!
Linux下追踪函数调用,打印栈帧的更多相关文章
- C语言函数调用及栈帧结构
source:http://blog.csdn.net/qq_29403077/article/details/53205010 一.地址空间与物理内存 (1)地址空间与物理内存是两个完全不同的概念, ...
- linux下使用小票打印
linux下使用小票打印 打印机: Xprinter XP-58IIH指令支持: ESC/POS接口: USB, 蓝牙 Linux系统: Centos7 蓝牙配对很快, 配对好后就是连接状态. 但很快 ...
- 从汇编角度来理解linux下多层函数调用堆栈执行状态
注:在linux下开发经常使用的辅助小工具: readelf .hexdump.od.objdump.nm.telnet.nc 等,详细能够man一下. 我们用以下的C代码来研究函数调用的过程. C ...
- 从汇编角度来理解linux下多层函数调用堆栈运行状态
我们用下面的C代码来研究函数调用的过程. C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int bar(int c, int d) { ...
- CTF必备技能丨Linux Pwn入门教程——调整栈帧的技巧
Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...
- Linux下调试程序方法
您可以用各种方法来监控运行着的用户空间程序:可以为其运行调试器并单步调试该程序,添加打印语句,或者添加工具来分析程序.本文描述了几种可以用来调试在 Linux 上运行的程序的方法.我们将回顾四种调试问 ...
- linux下gcc编译多个源文件、gdb的使用方法
一. gcc常用编译命令选项 假设源程序文件名为test.c. 1. 无选项编译链接 用法:#gcc test.c 作用:将test.c预处理.汇编.编译并链接形成可执行文件.这里未指定输出文件,默认 ...
- Linux下C程序的编辑,编译和运行以及调试
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...
- Linux下程序的机器级表示学习心得
Linux下程序的机器级表示学习心得 上周学习完Linux程序的机器级表示后,对于其中有些还是掌握的不太透彻.对于老师提出的关于本章一些细节的问题还是有不会,所以又重新温习了一下上周的学习内容,以下为 ...
随机推荐
- 进军es6(2)---解构赋值
本该两周之前就该总结的,但最近一直在忙校招实习的事,耽误了很久.目前依然在等待阿里HR面后的结果中...但愿好事多磨!在阿里的某轮面试中面试官问到了es6的掌握情况,说明es6真的是大势所趋,我们更需 ...
- UIWebview 禁止某个方向滚动
Enable Horizontal scrolling and disable Vertical scrolling: myWebView.scrollView.delegate = self; [m ...
- date 、cal、bc
date cal date是显示日期与时间 date +%Y/%M/%D date +%Y/%m/%d date +%H:%M cal cal 2016
- 让IE6兼容position:fixed
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 397. Integer Replacement
先正统做法. public class Solution { public int integerReplacement(int n) { if(n == 1) return 0; int res = ...
- xutils Error:(37, 39) 错误: 无法访问HttpRequestBase 找不到org.apache.http.client.methods.HttpRequestBase的类文件
Android 6.0(api 23)SDK已经强制移除httpclient 解决方案: 1降低api 2build.gradle中添加一句话 android { useLibrary'org.apa ...
- Yii2 自动更新时间created_at updated_at
创建model之后,新建一条记录,结果设计的表中created_at 字段 updated_at 字段 都是datetime 类型的,却不能自动插入当前时间.查看了资料,解决如下: 1.在class ...
- 理解事件捕获。在限制范围内拖拽div+吸附+事件捕获
一.实现的效果是在限制范围内拖拽div+吸附+事件捕获. 这里需要理解的是事件捕获,这个事件捕获也是为了兼容div在拖拽过程中,文本不被选中这个问题. 如此良辰美景,拖拽也可以很洒脱哈.先看看图, 二 ...
- PL/SQL:使用pragma restrict_references限制包权限
在看别人的代码的时候.发现了例如以下的编译指令. pragma restrict_references(get_attribute_name, wnds); get_attribute_name是一个 ...
- [Node.js] Exporting Modules in Node
In this lesson, you will learn the difference between the exports statement and module.exports. Two ...