C++ 如何在当前函数内 知道是哪个函数调用了当前函数 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mjy2
V2EX    问与答

C++ 如何在当前函数内 知道是哪个函数调用了当前函数

  •  
  •   mjy2 2022-05-31 16:49:42 +08:00 1761 次点击
    这是一个创建于 1233 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在实习中,遇到了一些问题。问下有没有大佬帮忙解答一下~ 有个触发器被指针 A 与 B 注册为回调函数,我要在触发器函数内查看是 A 调用了还是 B 调用了该触发器。 如果不添加额外的引用参数(自研引擎,不好改),该怎么实现呢?

    4 条回复    2022-05-31 18:10:57 +08:00
    Donahue
        1
    Donahue  
       2022-05-31 17:05:54 +08:00
    https://stackoverflow.com/questions/3899870/print-call-stack-in-c-or-c
    找到了一些可能有用的信息~

    google 关键字 c++ call stack
    mjy2
        3
    mjy2  
    OP
       2022-05-31 18:06:45 +08:00
    @Donahue 看了下是返回内存地址,那么每次运行的话,得出的内存地址都会不同嘛
    anonymous256
        4
    anonymous256  
       2022-05-31 18:10:57 +08:00
    在你的触发器函数里面,解开函数调用栈就可以了。三种常用的办法:

    1. gcc 内置宏__builtin_return_address:非常粗略的低级方法。这会在堆栈上的每一帧上获得函数的返回地址。注意:只是地址,不是函数名。所以需要额外的处理来获取函数名。
    2. glibc 的 backtrace 和 backtrace_symbols:可以获取调用堆栈上函数的实际符号名称。
    3. libunwind 库

    参考自: https://eli.thegreenplace.net/2015/programmatic-access-to-the-call-stack-in-c/

    根据上述文章提到的办法,采用 libunwind 库,我简单修改了下它的代码:
    1. 代码示例

    ```
    // example.cpp

    #include <libunwind.h>
    #include <stdio.h>

    // Call this function to get a backtrace.
    void backtrace() {
    unw_cursor_t cursor;
    unw_context_t context;

    // Initialize cursor to current frame for local unwinding.
    unw_getcontext(&context);
    unw_init_local(&cursor, &context);

    // Unwind frames one by one, going up the frame stack.
    while (unw_step(&cursor) > 0) {
    unw_word_t offset, pc;
    unw_get_reg(&cursor, UNW_REG_IP, &pc);
    if (pc == 0) {
    break;
    }
    printf("0x%lx:", pc);

    char sym[256];
    if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
    printf("(caller function: %s+, offset: 0x%lx)\n", sym, offset);
    } else {
    printf(" -- error: unable to obtain symbol name for this frame\n");
    }
    }
    }

    void foo1() {
    backtrace(); // <-------- backtrace here!
    }

    void foo2() {
    backtrace(); // <-------- backtrace here!
    }


    int main(int argc, char **argv) {
    foo1(); // <-----在函数 foo1()和 foo2()中可以看到整个的调用栈。
    printf("\n");
    foo2();
    return 0;
    }

    ````

    2. 编译前安装依赖(以 ubuntu 为例):
    sudo apt install libunwind-dev

    3. 编译指令:
    g++ -o example example.cpp -L /usr/local/lib -lunwind
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5809 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 43ms UTC 01:47 PVG 09:47 LAX 18:47 JFK 21:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86