LinuxX86中打印堆栈的简易使用说明

news/2024/7/6 6:03:27

在某些多路径的函数(例如退出),我们希望通过在日志中打印堆栈,确认调用途径,以定位一些奇怪的业务逻辑问题。
在Linux中,我们可以使用backtrace函数进行追踪。
*Android不支持此方法

1.使用示例

*以下代码节选自backtrace的man

int j, nptrs;
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, 100);
strings = backtrace_symbols(buffer, nptrs);
if (strings != NULL)
{
   for (j = 0; j < nptrs; j++)
       printf("%s\n",strings[j]);
   free(strings);
}

打印结果示例

lib/libpt.so.2.12.8(_ZN7PThread9TerminateEv+0x106) [0x7ffff783e932]
lib/libpt.so.2.12.8(_ZN8PProcess11PreShutdownEv+0x31b) [0x7ffff78696e9]
lib/libpt.so.2.12.8(_ZN8PProcessD1Ev+0x82) [0x7ffff783f422]
/opt/code/server_cloud/pkg/H323Gateway(_ZN8CMainAppD1Ev+0x35) [0x4d3ee9]
/opt/code/server_cloud/pkg/H323Gateway(_ZN8CMainAppD0Ev+0x18) [0x4d3f18]
/opt/code/server_cloud/pkg/H323Gateway(H323GW_UnInit+0x39) [0x4f8e98]
/opt/code/server_cloud/pkg/H323Gateway(main+0x28) [0x4f8ecd]
/lib64/libc.so.6(__libc_start_main+0xf5) [0x7ffff4f46505]
/opt/code/server_cloud/pkg/H323Gateway() [0x4be389]

2. 进阶玩法-崩溃时自动打印堆栈

在某些特殊情况下,我们无法生成CORE(可能是存储空间问题,或者其他问题);那么可以借用这个代码,简单定位一些明显的逻辑问题


void OnCrash(int nSig)
{
    switch (nSig)
    {
    case SIGFPE:
        printf("%s\n", "Program Crashed with SIGFPE: ");
        break;
    case SIGSEGV:
        printf("%s\n", "Program Crashed with SIGSEGV: ");
        break;
    case SIGBUS:
       	printf("%s\n", "Program Crashed with SIGBUS: ");
        break;
    }
    int j, nptrs;
    void *buffer[100];
    char **strings;
    nptrs = backtrace(buffer, 100);
    strings = backtrace_symbols(buffer, nptrs);

    if (strings != NULL)
    {
        for (j = 0; j < nptrs; j++)
            printf("%s\n", strings[j]);
        free(strings);
    }
   
    signal(SIGSEGV, SIG_DFL);
    signal(SIGFPE, SIG_DFL);
    signal(SIGBUS, SIG_DFL);
    raise(SIGQUIT); // Dump core
    _exit(-1); // Fail safe if raise() didn't dump core and exit
}

int main(int argc, char** argv)
{
	//……
	//也可以不在main中,在其他初始化必然经过的代码中
    signal(SIGSEGV, OnCrash);
    signal(SIGFPE, OnCrash);
    signal(SIGBUS, OnCrash);
    //……
}

3. 常见问题

  • Q:我的打印中只显示了地址,没有显示具体的函数名,是怎么回事?
    A:需要在CFLAGS参数中,增加 -rdynamic

  • Q:我还想知道具体的行号,怎么处理?
    A:可以将最后方括号里面的函数地址,用addr2line函数配套EXE来解决。此方法同样可以解决没有打印具体函数名时的排查问题。

示例:

addr2line --exe=H323Gateway -i 0x4f8e98

结果:

/opt/code/server_cloud/applications/h323gw/main.cpp:85 (discriminator 1)

http://www.niftyadmin.cn/n/1335558.html

相关文章

学习 python 的 pytest 框架需要的基础知识和学习准备

学习 python 的 pytest 框架需要的基础知识和学习准备测试从业者学习 python 应该掌握的内容: 首先是变量和数据类型&#xff0c;其次列表、字典以及 Json 的一些处理&#xff0c;再者就是循环 判断以及函数或类这些内容。 其中的重点&#xff1a; 1.循环判断以及字典这块是重点…

分享5个高质无损音乐网站,歌曲很丰富,爱听歌的小伙伴有耳福了

生活中很多人都离不开音乐&#xff0c;散步的时候听音乐&#xff0c;等待的时候听着音乐&#xff0c;心情不好的时候听音乐&#xff0c;不管走到哪&#xff0c;有音乐的陪伴一点也不寂寞&#xff0c;不同音乐的旋律给我们带来不同的心情&#xff0c;今天小编就给爱听音乐的小伙…

简易DOCKER/K8S使用心得

1. DOCKER安装 1.1 前置环境 首先&#xff0c;如果使用CentOS&#xff0c;你至少需要7.4以上。从内核角度来说&#xff0c;建议使用8.2及以上。 如果是7.4以下的版本&#xff0c;可以通过设置仓库到7.4以上版本&#xff0c;再 yum install centos-release kernel #实际上安装…

动画---分块运动

动画---分块运动 package com.example.test;import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.gra…

爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!

1 前言近期&#xff0c;有些朋友问我一些关于如何应对反爬虫的问题。由于好多朋友都在问&#xff0c;因此决定写一篇此类的博客。把我知道的一些方法&#xff0c;分享给大家。博主属于小菜级别&#xff0c;玩爬虫也完全是处于兴趣爱好&#xff0c;如有不足之处&#xff0c;还望…

组件prop检验

Vue.js中的父子组件相信都已经是大家很常用到的功能了&#xff0c; 父组件通过props属性向子组件传值子组件通过自定义事件向父组件传值 那么我们怎么去校验props属性中的类型呢 笔者列出以下几种方法&#xff1a; 1&#xff1a;直接检测 如果将 string 换成Number 那么在控制台…

网上下载文档需要付费?试试这几招,老师傅一般都会使用

平时在上网找资料时候&#xff0c;当发现下载时候需要付费&#xff0c;我们一般该怎么办呢&#xff1f;扎心啦老铁&#xff0c;难道你就甘心放弃现在找到的文档资料&#xff1f; 其实不用的啦&#xff01;这里为大家汇总了几个下载文档的方法&#xff0c;大家如果有什么需要下…

也谈GB28181码流收发

1.前置文章 PS封装格式&#xff1a;GB28181协议RTP传输 H265的国标PS流打包 这两篇文章里面有的就不细说了 2.发送的规则细节 在国标中&#xff0c;不需要对H264/H265裸流进行进一步的去NAL等操作&#xff0c;直接发裸流即可。如果一个包发不下&#xff0c;可以分包发送&a…