古月不傲 发表于 2021-1-13 00:31

输出函数调用过程

本帖最后由 古月不傲 于 2021-1-13 01:00 编辑

#include <iostream>
#include <string>
#include <cxxabi.h>
#include <execinfo.h>

void bb();
void cc();

// 输出函数回朔过程,并以C函数名的风格显示
std::string stackTrace(bool demangle)
{
        std::string                         stack;
        const int max_frames         = 250;
        void                                        *frame;
        // 第一个参数,返回的回朔地址缓存区
        // 第二个参数,要容纳多少个地址
        // 返回值,栈帧编号,表示第几个函数
        int nptrs                                 = backtrace(frame, max_frames);
        // 第一个参数,已经接收到的回朔地址缓存区
        // 第二个参数,接收到的栈帧编号
        char** strings                         = backtrace_symbols(frame, nptrs);

        if (strings)
        {
                size_t len = 256;
                // 分配内存
                char* demangled = demangle ? static_cast<char*>(::malloc(len)) : nullptr;

                // 解析每个地址成字符串
                for (int i = 1; i < nptrs; ++i)// skipping the 0-th, which is this function
                {
                        if (demangle)
                        {
                                char* left_par         = nullptr;
                                char* plus                 = nullptr;

                                // 解析每个字符 找到( + 号的位置
                                for (char* p = strings; *p; ++p)
                                {
                                        if (*p == '(')
                                                left_par = p;
                                        else if (*p == '+')
                                                plus = p;
                                }

                                // ( && +
                                if (left_par && plus)
                                {
                                        *plus = '\0';        // 将函数名后面的 +号先清0 以便截取函数名
                                        int status = 0;
                                        // 将函数名翻译成C语言风格
                                        char* ret = abi::__cxa_demangle(left_par+1, demangled, &len, &status);
                                        *plus = '+';        // 重新设置 +号
                                        if (status == 0)
                                        {
                                                demangled = ret;// ret could be realloc()
                                                // 追加到statckstrings.start -- "(+1"
                                                stack.append(strings, left_par+1);
                                                // 追加函数名称
                                                stack.append(demangled);
                                                // 追加函数名称之后的部分,一直到\0
                                                stack.append(plus);
                                                // 添加换行
                                                stack.push_back('\n');
                                                continue;
                                        }
                                }
                        }
                        // Fallback to mangled names
                        stack.append(strings);
                        stack.push_back('\n');
                }
                free(demangled);
                free(strings);
        }
        return stack;
}

void a()
{
        bb();
}

void dd()
{
        printf("%s\n", stackTrace(true).c_str());
}

void bb()
{
        int size = 200;
        void *buf{};
        int c = backtrace(buf, 200);
        char **str = backtrace_symbols(buf, c);
        for (int i = 0; i < c; i++)
                printf("%s\n", str);
        free(str);
        cc();
}

void cc()
{
        printf("%s\n", stackTrace(true).c_str());
        dd();
}


int main()
{
        a();

        return 0;
}


编译时加上:   -rdynamic

z1991627 发表于 2021-1-13 08:25

说个实话,我是把一本基础C的书看完了 为什么看不懂你的代码!看不我不适合编程

2513002960 发表于 2021-1-13 11:34

z1991627 发表于 2021-1-13 08:25
说个实话,我是把一本基础C的书看完了 为什么看不懂你的代码!看不我不适合编程

这个好像是c++我也不会?

古月不傲 发表于 2021-1-13 12:44

本帖最后由 古月不傲 于 2021-1-13 12:46 编辑

z1991627 发表于 2021-1-13 08:25
说个实话,我是把一本基础C的书看完了 为什么看不懂你的代码!看不我不适合编程
这是muduo库的源码,主要用于异常回朔,看不懂可能是你没静下心,或者你的基础不够,还不能阅读第三方的源码。
这里面无非就用到了三个函数,加点指针的东西,静下心,一般都能看懂。
页: [1]
查看完整版本: 输出函数调用过程