当前位置: 首页 > article >正文

Linux C++语言函数调用栈打印

在Linux 系统应用程序开发过程中,会遇到调用栈打印的场景,在上一篇文章《Linux C语言函数调用栈打印》中讲述了C语言函数调用栈的用法。C++ 语言的函数调用栈与C语言类似,只不过符号翻译有所不同。话不多说,直接上代码和运行结果。

main.cpp

// main.cpp
#include "a.h"
int main() {
    A a;
    a.run();
    return 0;
}

a.h

// a.h
#include <string.h>
#include <iostream>
#include <string>
#include <vector>
using std::string;
using std::vector;

class A {
public:
    A() {}
    ~A() {}
    int run();
};

a.cpp

// a.cpp
#include "a.h"
#include <execinfo.h>
#include "backtrace.h"

int A::run() {
    void* callstack[128];
    size_t frames = backtrace(callstack, 128);
    vector<string> symbols = BacktraceCxxSymbols(callstack, frames);
    for (auto s : symbols)
        std::cout << s << std::endl;

    std::cout << "------------------------" << std::endl;

    char** strings = backtrace_symbols(callstack, frames);
    for (int i = 0; i < frames; i++) {
        std::cout << strings[i] << std::endl;
    }
    free(strings);
    return 0;
}

backtrace.h

//backtrace.h
#include <string>
#include <vector>

std::vector<std::string> BacktraceCxxSymbols(void** array, int size);

backtrace.cpp

//backtrace.cpp
#include <cxxabi.h>
#include <string.h>
#include "backtrace.h"
using std::vector;
using std::string;

// #define __USE_GNU
#include <dlfcn.h>

vector<string> BacktraceCxxSymbols(void** array, int size) {
    int status = 0;
    char buf[4096] = {0};
    char* p_demangled_name = NULL;
    vector<string> symbol_vec;
    Dl_info info = {0};
    int i = 0;
    void* addr_offset = NULL;
    if (NULL == array || 0 == size) {
        return symbol_vec;
    }

    for (i = 0; i < size; i++) {
        memset(&info, 0, sizeof(Dl_info));
        if (0 == dladdr(array[i], &info)) {
            continue;
        }
        if (info.dli_saddr) {
            addr_offset = (void*)((char*)array[i] - (char*)info.dli_saddr);
        } else {
            addr_offset = (void*)((char*)array[i] - (char*)info.dli_fbase);
        }
        if (!info.dli_sname) {
            info.dli_sname = "";
        }
        if (!info.dli_fname) {
            info.dli_fname = "";
        }
        memset(buf, 0, sizeof(buf));
        p_demangled_name = abi::__cxa_demangle(info.dli_sname, NULL, NULL, &status);
        if (0 == status && p_demangled_name) {
            snprintf(buf, sizeof(buf), "%s(%s+%p) [%p]", info.dli_fname, p_demangled_name, addr_offset, array[i]);
        } else {
            snprintf(buf, sizeof(buf), "%s(%s+%p) [%p]", info.dli_fname, info.dli_sname, addr_offset, array[i]);
        }
        if (p_demangled_name) {
            free(p_demangled_name);
        }
        symbol_vec.push_back(buf);
    }
    return symbol_vec;
}

Makefile

CXXFLAGES:= -fpic -O0 -g
# CXXFLAGES:= 

all: test
	# export LD_LIBRARY_PATH=/root/BASE1_0_r/build_x86:$LD_LIBRARY_PATH

test: main.o liba.so backtrace.so
	g++ -I ./ -o test main.o -L ./ -la -lbacktrace -ldl $(CXXFLAGES)

liba.so: a.o
	g++ -shared -o liba.so a.o

# libb.so: b.o
# 	g++ -shared -o libb.so b.o

backtrace.so: backtrace.o
	g++ -shared -o libbacktrace.so backtrace.o

a.o: a.cpp
	g++ $(CXXFLAGES) -c a.cpp

# b.o: b.c
# 	g++ $(CXXFLAGES) -c b.c

main.o: main.cpp
	g++ $(CXXFLAGES) -c main.c

backtrace.o: backtrace.cpp
	g++ $(CXXFLAGES) -c backtrace.cpp

clean: FORCE
	rm -rf *.o
	rm -rf *.so
	rm -rf test

FORCE:

运行结果

./test
/root/BASE1_0_r/build_x86/liba.so(A::run()+0x3a) [0x7fdea6260594]
./test(+0x11fd) [0x5636bb7a71fd]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7fdea5e46083]
./test(+0x110e) [0x5636bb7a710e]
------------------------
/root/BASE1_0_r/build_x86/liba.so(_ZN1A3runEv+0x3a) [0x7fdea6260594]
./test(+0x11fd) [0x5636bb7a71fd]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7fdea5e46083]
./test(+0x110e) [0x5636bb7a710e]

http://www.kler.cn/a/537496.html

相关文章:

  • 25/2/7 <机器人基础> 牛顿-欧拉递推公式,开闭环
  • 【Uniapp-Vue3】从uniCloud中获取数据
  • 无界构建微前端?NO!NO!NO!多系统融合思路!
  • 算法9--链表
  • grafana面板配置opentsdb
  • 额外题目汇总2-链表
  • MySQL 8.0.41安装教程(2025年2月8号)
  • Spring Boot和SpringMVC的关系
  • kafka消费端之消费者协调器和组协调器
  • 2023 Java 面试题精选30道
  • 【ROS2】【2025】Simulate a 6DoF Robotic Arm in Gazebo and ROS2
  • Vue 入门到实战 八
  • Oracle Database Free版本的各项许可限制
  • Windows 实用设置工具 v3.6.5:一键优化系统设置
  • TCP三次握手全方面详解
  • SSD1306 128*32屏幕驱动
  • Java 读取 Word 模板文档并替换内容生成新文档
  • 探索C语言:寻找数组中连续1的最大长度
  • 软考网络安全 软考网络安全员
  • 使用Python开发PPTX压缩工具
  • 【ORACLE】这个‘‘和null不等价的场景,deepseek你怎么看?
  • 解决Element UI中el-select下拉框因为选项内容过长导致下拉框宽度显示过长问题
  • 25/2/8 <机器人基础> 阻抗控制
  • 如何使用Gemini模型,国内如何订阅购买Gemini Pro的教程,Gemini Pro 免费试用操作步骤, 谷歌 aistudio 使用入口
  • 系统URL整合系列视频四(需求介绍补充)
  • 基于架构的软件设计(Architecture-Based Software Design, ABSD)