在程序调试过程中程序崩溃的情况时有发生,把出问题时的调用栈信息打印出来是一种不错的解决办法。

当然还有一些其他方法:https://www.cnblogs.com/jiangyibo/p/8653720.html

首先,介绍三个函数:

  1.int backtrace(void **buffer,int size);

    该函数用于获取当前线程的调用堆栈信息,信息被存放在buffer中,它是一个指针数组。

    参数size表示buffer中可以存放void*元素的个数,函数返回值是实际获取到的void*元素的个数。

  2.char **backtrace_symbols(void *const *buffer, int size);

    backtrace_symbols将backtrace函数获取的信息转化为一个字符串数组,参数buffer是从backtrace函数获取的指针数组,size是该数组中的元素个数(backtrace函数的返回值)。

    函数返回值是一个指向字符串数组的指针,它的大小同buffer相同。

    需要注意的是该函数返回的地址是通过malloc函数申请的空间,为了防止内存泄露,我们要手动调用free来释放这块内存。"free(函数返回的指针)"

  

  3.void backtrace_symbols_fd (void *const *buffer, int size, int fd);

    该函数与backtrace_symbols 函数功能类似,不同的是,这个函数直接把结果输出到文件描述符为fd的文件中,且没有调用malloc,不需要手动释放空间。

测试用例:

  main.c

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <execinfo.h> #define Size 128 void fun(void)
{
int *piTest = NULL;
*piTest = ;
} void signalHandler(int signalId)
{
int i = ;
int iNum = ;
void *pBuffer[Size] = {};
char **pszDebugInfo = NULL; iNum = backtrace(pBuffer, Size);
pszDebugInfo = backtrace_symbols(pBuffer, iNum); if (pszDebugInfo == NULL)
{
perror("backtrace_symbols");
exit(EXIT_FAILURE); // 表示没有成功执行程序
} for (i = ; i < iNum; i++)
{
printf(" [%02d] %s\n", i, pszDebugInfo[i]);
} free(pszDebugInfo); signal(signalId, SIG_DFL); raise(signalId);
} int main(int argc, char *argv[])
{
// SIGSEGV是当一个进程执行了一个无效的内存引用,
// 或发生段错误时发送给它的信号
signal(SIGSEGV, signalHandler); fun(); printf("----\n"); return ;
}

gcc -g -rdynamic main.c -o main

  -g      "objdump"的参数"-l","-S"要求编译时使用了-g之类的调试编译选项。

  -rdynamic  该参数是链接选项,不是编译选项。这主要是对可执行程序(elf)而言的,而编译动态库时,即使没有rdynamic选项,默认也会将非静态函数放入动态符号表中(刻意隐藏的函数除外)。默认情况下,可执行程序(非动态库)文件内我们定义的非静态函数,是不放到动态符号表中的,链接时只有加上"-rdynamic"才能将所有非静态函数加到动态符号表中。

./main

objdump -S -l ./main > info.txt

  objdump命令是用查看目标文件或者可执行的目标文件的构成的gcc工具。

  -l    --line-numbers 
  用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求编译时使用了-g之类的调试编译选项。
  -S    --source
  尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,效果比较明显。隐含了-d参数。 上图可以看到发生了段错误,从下往上可以看到错误大概是发生在"fun"函数,然后打开info.txt,查找有关地址"0a16"的行号:
  vim info.txt
  命令模式:/0a16

  可以看到"0a16"所在"main.c"的12行,而12号正好是"*piTemp = 2;"。

  这里只举例了可执行文件,同理的动态库(记得加-g)也可以按照这个办法来查找错误,这里就不细说了。

objdump和backtrace的配合使用的更多相关文章

  1. linux下寻找段错误的方法

    为了能够快速找到发生段错误的地方,记录以下两种方法. objdump和backtrace的配合使用 :https://www.cnblogs.com/jiangyibo/p/9507555.html ...

  2. Debug Hacks中文版——深入调试的技术和工具

    关键词:gdb.strace.kprobe.uprobe.objdump.meminfo.valgrind.backtrace等. <Debugs Hacks中文版——深入调试的技术和工具> ...

  3. Linux内核调试方法总结之反汇编

    Linux反汇编调试方法 Linux内核模块或者应用程序经常因为各种各样的原因而崩溃,一般情况下都会打印函数调用栈信息,那么,这种情况下,我们怎么去定位问题呢?本文档介绍了一种反汇编的方法辅助定位此类 ...

  4. 利用backtrace和objdump进行分析挂掉的程序

    转自:http://blog.csdn.net/hanchaoman/article/details/5583457 汇编不懂,先把方法记下来. glibc为我们提供了此类能够dump栈内容的函数簇, ...

  5. 嵌入式 linux下利用backtrace追踪函数调用堆栈以及定位段错误

    嵌入式 linux下利用backtrace追踪函数调用堆栈以及定位段错误 2015-05-27 14:19 184人阅读 评论(0) 收藏 举报  分类: 嵌入式(928)  一般察看函数运行时堆栈的 ...

  6. linux下利用backtrace追踪函数调用堆栈以及定位段错误

    一般察看函数运行时堆栈的方法是使用GDB(bt命令)之类的外部调试器,但是,有些时候为了分析程序的BUG,(主要针对长时间运行程序的分析),在程序出错时打印出函数的调用堆栈是非常有用的. 在glibc ...

  7. 用户态使用 glibc/backtrace 追踪函数调用堆栈定位段错误【转】

    转自:https://blog.csdn.net/gatieme/article/details/84189280 版权声明:本文为博主原创文章 && 转载请著名出处 @ http:/ ...

  8. backtrace和backtrace_symbols

    一般察看函数运行时堆栈的方法是使用GDB(bt命令)之类的外部调试器,但是,有些时候为了分析程序的BUG,(主要针对长时间运行程序的分析),在程序出错时打印出函数的调用堆栈是非常有用的. 在glibc ...

  9. kset学习demo以及Oops反汇编objdump调试例子【原创】

    写一个main.c gcc -c -g main.c objdump -S main.o > b.txt arm-none-linux-gnueabi-gcc -c -g a.c arm-non ...

随机推荐

  1. SAP Fiori Client

    iPhone资源->iPhone商务软件 SAP Fiori Client 固件要求:需要 iOS 9.0 或更高版本.与 iPhone.iPad 和 iPod touch 兼容. 利用适用于 ...

  2. 08.vue中样式-class

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. _reincarnation

    可以设定转生等级和转生需求.来奖励转生 `level`转生等级 `reqId` 转生需求 `rewId` 转生奖励 `gossipText` 菜单显示

  4. 将npm的注册表源设置为国内的镜像

    1.国内用户,建议将npm的注册表源设置为国内的镜像,可以大幅提升安装速度 2.国内优秀npm镜像推荐及使用:http://riny.net/2014/cnpm/ 淘宝npm镜像 ·搜索地址:http ...

  5. 移动Web UI库(H5框架)有哪些,看这里就够了

    前言 今年上半年,项目组在项目开发的过程中建立了一套风格统一,组件丰富完善,命名统一规范的PC端UI库,适用于做大型站点,该UI库也是应用到了整个平台的项目中,在各个项目组中进行推广.因为项目的保密性 ...

  6. Linux wc -l 统计文件行数存在的问题

    1.使用这种方式效率较低,而且不注意可能出现错误 find  . -name "*.pc" |xargs wc -l 直接查看 total 不是正确的值. 原因: 这种方式存在一个 ...

  7. 获取url "?" 后面的字符串

    今天写了一个URL “?” 后面的字符串 来改变当前页面的状态 首先需要获取当前页面的URL console.log(widow.location) 之后页面就会打印出来当前的URL 之后我们获取UR ...

  8. Matlab:高阶常微分三种边界条件的特殊解法(隐式Euler)

    函数文件1: function b=F(f,x0,u,h) b(1,1)=x0(1)-h*x0(2)-u(1); b(2,1)=x0(2)+h*x0(1)^2-u(2)-h*f; 函数文件2: fun ...

  9. mysql(5.5)安装后忘记密码

    查看mysql安装的路径

  10. Dropout, DropConnect ——一个对输出,一个对输入

    Deep learning: Dropout, DropConnect from:https://www.jianshu.com/p/b349c4c82da3 Dropout 训练神经网络模型时,如果 ...