先来了解三个函数

#include <execinfo.h>

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

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

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

int backtrace(void **buffer,int size)该函数用与获取当前线程的调用堆栈,获取的信息将会被存放在buffer中,它是一个指针数组。参数 size 用来指定buffer中可以保存多少个void* 元素。函数返回值是实际获取的指针个数,最大不超过size大小在buffer中的指针实际是从堆栈中获取的返回地址,每一个堆栈框架有一个返回地址。注意某些编译器的优化选项对获取正确的调用堆栈有干扰,另外内联函数没有堆栈框架;删除框架指针也会使无法正确解析堆栈内容char ** backtrace_symbols (void *const *buffer, int size)backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组. 参数buffer应该是从backtrace函数获取的数组指针,size是该数组中的元素个数(backtrace的返回值),函数返回值是一个指向字符串数组的指针,它的大小同buffer相同.每个字符串包含了一个相对于buffer中对应元素的可打印信息.它包括函数名,函数的偏移地址,和实际的返回地址现在,只有使用ELF二进制格式的程序和苦衷才能获取函数名称和偏移地址.在其他系统,只有16进制的返回地址能被获取.另外,你可能需要传递相应的标志给链接器,以能支持函数名功能(比如,在使用GNU ld的系统中,你需要传递(-rdynamic))
backtrace_symbols生成的字符串都是malloc出来的,但是不要最后一个一个的free,因为backtrace_symbols是根据backtrace给出的call stack层数,一次性的malloc出来一块内存来存放结果字符串的,所以,像上面代码一样,只需要在最后,free backtrace_symbols的返回指针就OK了。这一点backtrace的manual中也是特别提到的。
注意:如果不能为字符串获取足够的空间函数的返回值将会为NULLvoid backtrace_symbols_fd (void *const *buffer, int size, int fd)backtrace_symbols_fd与backtrace_symbols 函数具有相同的功能,不同的是它不会给调用者返回字符串数组,而是将结果写入文件描述符为fd的文件中,每个函数对应一行.它不需要调用malloc函数,因此适用于有可能调用该函数会失败的情况。

程序测试:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <execinfo.h>void out_stack(char *sig);void signal_exit(int dunno)
{ char* signal_str = "";char dunno_str[10] = {0};sprintf(dunno_str, "%d", dunno);switch (dunno) {case 1:signal_str = "SIGHUP(1)";break;case 2:signal_str = "SIGINT(2:CTRL_C)"; //CTRL_Cbreak;case 3:signal_str = "SIGQUIT(3)";break;case 6:{signal_str = "SIGABRT(6)";out_stack(signal_str);}break;case 9:signal_str = "SIGKILL(9)";break;case 15:signal_str = "SIGTERM(15 KILL)"; //kill break;case 11:{signal_str = "SIGSEGV(11)"; //SIGSEGV out_stack(signal_str);}break; default:signal_str = "OTHER";break;}exit(0);
}static void output_addrline(char addr[])
{char cmd[256];char line[256];char addrline[32]={0,};char *str1, *str2;FILE* file;str1 = strchr(addr,'[');str2 = strchr(addr, ']');if(str1 == NULL || str2 == NULL){return;} memcpy(addrline, str1 + 1, str2 -str1);snprintf(cmd, sizeof(cmd), "addr2line -e /proc/%d/exe %s ", getpid(), addrline);file = popen(cmd, "r");if(NULL != fgets(line, 256, file)) {printf("%s\n", line);}pclose(file);
}
void out_stack(char *sig)
{void *array[32];size_t size;char **strings;int i;printf("%s\n", sig);size = backtrace (array, 32);strings = backtrace_symbols (array, size);if (NULL == strings){printf("backtrace_symbols\n");return ;}for (i = 0; i < size; i++){printf("%s",strings[i]);output_addrline(strings[i]);    }free(strings);
}
void test3(int n)
{char *str;printf("in test3 [%d]\n", n);strcpy(str, "123");
}
void test2(int n)
{printf("in test2 [%d]\n", n);test3(3);
}
void test1(int n)
{printf("in test1 [%d]\n", n);test2(2);
}
int main()
{signal(SIGHUP, signal_exit); signal(SIGINT, signal_exit);signal(SIGQUIT, signal_exit);signal(SIGABRT, signal_exit);signal(SIGKILL, signal_exit);signal(SIGTERM, signal_exit);signal(SIGSEGV, signal_exit);test1(1);
}

注意编译的时候要加-g 和 -rdynamic选项

linux c 程序异常退出时打印堆栈调用信息相关推荐

  1. 安卓软件错误log_Android编程实现捕获程序异常退出时的错误log信息功能详解

    本文实例讲述了Android编程实现捕获程序异常退出时的错误log信息功能.分享给大家供大家参考,具体如下: 很多时候我们程序无缘无故的就挂掉了,让我们一头雾水,如果刚好我们在调试,那我们可以通过错误 ...

  2. java线程异常终止_java线程莫名异常退出时,如何捕获异常信息

    之前有同事说他的程序里的线程时常莫名退出,日志中没有任何异常信息. 目前我知道的可以获取线程异常信息的方法主要有 1.Future>和ScheduledFuture>的get()方法 2. ...

  3. 如何定位导致程序异常退出的Bug?

    一 引言 我们写代码的时候经常会遇到一些Bug导致程序异常退出,比如访问了空指针.在大多数情况下,我们能够根据经验和IDE本身提供的调试功能来定位问题,并找到解决方案.但最近在工作中遇到了一个问题,一 ...

  4. Linux下程序崩溃dump时的 core文件的使用方法

    Linux下程序崩溃dump时的 core文件的使用方法 1.在启动程序前执行 ulimit -c unlimited unlimited 表示生成文件的大小限制,也可以修改为自定义的大小,例如: u ...

  5. 如何让程序异常退出后重启

    标 题:如何让程序异常退出后重启 发信人:蔡子楠 出处:http://www.freeeim.com/ 时 间:2008-02-14 11:25:22 "程序 FreeEIM.exe 遇到问 ...

  6. main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出。

    main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出. 参考文章: (1)main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出. (2)https://www.cnbl ...

  7. C# 程序异常关闭时的捕获

    C# 程序异常关闭时的捕获 参考文章: (1)C# 程序异常关闭时的捕获 (2)https://www.cnblogs.com/hsiang/p/9388186.html (3)https://www ...

  8. C#WinForm程序异常退出的捕获、继续执行与自动重启

    C#WinForm程序异常退出的捕获.继续执行与自动重启 参考文章: (1)C#WinForm程序异常退出的捕获.继续执行与自动重启 (2)https://www.cnblogs.com/mq0036 ...

  9. 使用c++filt查看trafficserver堆栈调用信息

    在实际运维中,我们经常遇到Apache Traffic Server遇到段错误时,在traffic.out中留下的堆栈调用信息,比如下面的 FATAL: ../.././ats-4.2.0/proxy ...

最新文章

  1. 口语学习Day1:天气
  2. 艾媒:第三方应用商店形成BAT3争霸格局
  3. LeetCode Smallest Range
  4. java二叉树求权值_百度笔试题目:二叉树路径权值和【转】
  5. [今日白学]组件的基础的基础的基础
  6. 敏捷无它,唯持续改进
  7. java文件ftp下载,java ftp下载文件夹内所有文件,java 下载ftp文件夹下所有文件
  8. 计算机网络基础之数据交换技术
  9. java中,参数后面跟三个点(...)的含义
  10. 千千静听V5.6 Beta3 美化增强版
  11. android 联系人 字母索引,Android手机联系人带字母索引的快速查找
  12. DevOps名言警句 - 2021
  13. 有关爬虫浏览量的问题
  14. EIGRP优化—末节路由简介
  15. 向日葵 11.0.0.34335 中文版 (老牌国产远程控制软件)
  16. 现代基准测试程序种类以及使用方法
  17. 软件磁盘阵列(Software RAID)介绍
  18. 台式计算机怎么加一个硬盘,台式机添加硬盘方法
  19. 2018 Macbook pro 15(10.13.6)安装Nvidia 1070(Aorus Gaming Box)显卡驱动
  20. 美国计算机科学排,美国大学计算机科学computer science专业排名

热门文章

  1. [SV]SystemVerilog压缩数组(Packed Array)和非压缩数组( Unpacked Array)
  2. C++控制台清屏函数
  3. App打开小程序,小程序打开App
  4. 文件上传漏洞的小总结
  5. 微信公众号文章中的图片处理有哪些技巧?看这篇就够了。
  6. 关于GPS实际精度比较低,而且频率低,但是无人机GPS定点却定得和钉子一样
  7. cufflinks suit
  8. Ubuntu查看主机名和修改主机名
  9. Spring Batch单元测试示例
  10. sklearn 命令行安装_sklearn安装