【问题标题】:predefined macro to identify the calling function?预定义的宏来识别调用函数?
【发布时间】:2014-03-19 19:49:31
【问题描述】:

是否有任何预定义的宏来识别调用函数。

打印我们使用的当前函数名

printf("%s", __FUNCTION__);

如果函数a调用b并且控制在b中,那么有没有办法找出a

【问题讨论】:

  • 宏在编译时被解析,无法知道哪个函数调用了当前函数。在运行时,有一些环境库可以显示调用堆栈,如下所示:stackoverflow.com/a/691742/104774
  • 不过,这是一个疯狂的想法。 (1) 创建一个“调用堆栈”数组,(2) 添加function entry/exit codes 以更新堆栈,(3) .. 利润。不过,这取决于您的编译器。
  • @Jongware (特定于编译器的)前置/后置函数是一个好主意,除非它们会面临同样的问题(因为 FUNCTION 将是那些函数,而不是调用者)。您将需要一个 pre/post 宏,这可能通过简单的编译器标志不存在。

标签: c++ c macros


【解决方案1】:

没有。为此,预处理器必须知道哪些函数调用了您的函数。但是,该信息当时不可用。在(动态或静态)库的情况下,这些信息实际上在编译时永远不会完全可用。

编辑:正如@stefaanv 在评论中所说,您必须使用运行时手段,例如他在运行时链接的 StackWalker 库。这是您知道哪个函数调用您的函数的唯一点。

【讨论】:

    【解决方案2】:

    您可以使用堆栈跟踪,了解所有方法的流程。

    void StackTrace::printStackTrace( ){
    std::cout<<"stack Trace\n";
    std::cerr<<"stachTrace\n";
    // storage array for stack trace address data
    void* addrlist[maxFrame+1];
    
    // retrieve current stack addresses
    int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
    if (addrlen == 0) {
        std::cerr<<"  <empty, possibly corrupt>\n";
        std::cout<<" <empty, possibly corrupt\n";
    
    
    }
    // resolve addresses into strings containing "filename(function+address)",
    // this array must be free()-ed
    char** symbollist = backtrace_symbols(addrlist, addrlen);
    // allocate string which will be filled with the demangled function name
    size_t funcnamesize = 256;
    char* funcname = (char*)malloc(funcnamesize);
    // iterate over the returned symbol lines. skip the first, it is the
    // address of this function.
    for (int i = 1; i < addrlen; i++){
        char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
        // find parentheses and +address offset surrounding the mangled name:
        // ./module(function+0x15c) [0x8048a6d]
        for (char *p = symbollist[i]; *p; ++p){
            if (*p == '(')
                begin_name = p;
            else if (*p == '+')
                begin_offset = p;
            else if (*p == ')' && begin_offset) {
                end_offset = p;
                break;
    
            }
        }
        if (begin_name && begin_offset && end_offset
                && begin_name < begin_offset){
            *begin_name++ = '\0';
            *begin_offset++ = '\0';
            *end_offset = '\0';
            // mangled name is now in [begin_name, begin_offset) and caller
            // offset in [begin_offset, end_offset). now apply
            // __cxa_demangle():
            int status;
                        char* ret =abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
            if (status == 0) {
                funcname = ret; // use possibly realloc()-ed string
                //fprintf(out, "  %s : %s+%s\n",
                    //  symbollist[i], funcname, begin_offset);
                std::cerr<<symbollist[ i ]<<funcname<<begin_offset<<std::endl;
        std::cout<<symbollist[ i ] << funcname << begin_offset<<std::endl;
            }else{
    
            //fprintf(out, "  %s\n", symbollist[i]);
                std::cerr<<symbollist[ i ]<<std::endl;
        std::cout<<symbollist [ i ]<<std::endl;
            }
        }
    }
    free(funcname);
    free(symbollist);
    

    }

    此代码将为您提供概念,我从我的一个项目中复制了它。

    【讨论】:

    • @anderas .. 是的,我只熟悉 linux (g++)
    猜你喜欢
    • 1970-01-01
    • 2013-02-24
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多