【问题标题】:How to convert a function pointer to function name?如何将函数指针转换为函数名?
【发布时间】:2017-04-04 01:25:13
【问题描述】:

我现在有一组具有相同功能的函数,

func_pointer_t func_array[] = {func_1, func_2, func_3, ...};

我想开发一个程序,它遍历所有数组成员并将输出转储到另一个 .dat 数据文件。输出应具有以下格式:

func_1 func_1_output
func_2 func_2_output
func_3 func_3_output
...

所以我的问题是——在遍历数组成员时,我们如何让程序知道函数指针指向哪个函数名(例如 func_array[0] 指向 func_1)?

【问题讨论】:

  • 你标记了 c++,为什么不使用地图
  • 变量/函数名称在编译过程中丢失。他们只是在帮助程序员。
  • 它是 C++。很抱歉没有看到关于这个问题的先前帖子。是的,拥有地图结构似乎是个好主意:)
  • @alk:函数名称可能在可执行文件中徘徊。这取决于它是否有符号。不过,对这些符号的访问是非常特定于平台的。

标签: c++


【解决方案1】:

backtrace_symbols_fd

这并不完美,但也许它表明了一条路径。改编自How to get function's name from function's pointer in Linux kernel?

main.cpp

#include <execinfo.h>
#include <stdio.h>
#include <unistd.h>

void foo(void) {
    printf("foo\n");
}

int main(int argc, char *argv[]) {
    void *funptr = &foo;
    backtrace_symbols_fd(&funptr, 1, STDOUT_FILENO);
    printf("%p\n", foo);
    return 0;
}

编译运行:

g++ -std=c++11 main.cpp -rdynamic
./a.out 

输出:

./a.out(_Z3foov+0x0)[0x562ff384893a]
0x562ff384893a

所以我们看到了 foo 的错误名称 _Z3foov 被输出:

echo _Z3foov | c++filt

我不知道如何解决的缺点是:

  • 需要使用 -rdynamic 修改构建,因此不适用于静态链接,并且可能还有其他缺点
  • 不会自动拆解

但我确实认为研究回溯机制是一个不错的选择,我已在以下位置对其进行了进一步调查:print call stack in C or C++

也许我们也可以摆脱调试信息:Programmatically get debug information 如果可能的话,这实际上可能是最稳定的方法。但目前没有人知道该怎么做。

在 Ubuntu 18.04、GCC 7.4.0 中测试。

【讨论】:

    【解决方案2】:

    您可以通过存储一个配对数组来简单地跟踪名称,该数组将匹配函数指针及其名称:

    std::pair<const char*, func_pointer_t>[] func_array = {
        {"func_1", func_1},
        {"func_2", func_2},
        {"func_3", func_3}
    };
    

    您现在也可以使用它的名称了。

    如果你想要,你甚至可以使用地图:

    std::map<std::string, func_ptr_t> func_array {
        {"func_1", func_1},
        {"func_2", func_2},
        {"func_3", func_3}
    };
    

    【讨论】:

    • 这里的“艺术”是什么意思?
    • 是的,我有一个!
    【解决方案3】:

    没有标准的方法来归档您所查找的内容。所有可能的解决方案要么涉及系统相关的方法来将函数地址解析为它们的名称(即使这样也不一定总是有效),或者像这样更改 func_array:

    struct {
        func_pointer_t func;
        const char * name;
    } func_array[] = {
        { func_1, "func_1" },
        { func_2, "func_2" },
        { func_3, "func_3" },
        ...
    };
    

    您可以使用宏来简化工作:

    #define FUNC_DEF(func) { func, #func },
    

    然后像这样使用它:

    struct {
        func_pointer_t func;
        const char * name;
    } func_array[] = {
        FUNC_DEF(func_1)
        FUNC_DEF(func_2)
        FUNC_DEF(func_3)
        ...
    };
    

    所以,如果这是您的选择,那么您就有了解决方案。如果没有,您必须说明您的目标是什么系统。

    存在更多 C++ish 解决方案 - 例如 Govind Parmar 暗示的 std::map 解决方案,您可以在其中迭代并获取键 值对。

    【讨论】:

    • Nitting:你最好把宏大写。
    【解决方案4】:

    您需要记住,在汇编/机器代码级别没有“函数名称”(除非您在构建中有调试信息);只有地址指示函数从哪里开始。

    您必须使用数据结构来跟踪这些内容。如果您使用的是 C++,请使用 map&lt;string, function_pointer&gt;,正如评论者 @MyUsername112358 指出的那样。

    【讨论】:

    • void *function_ptr; 始终是一个错误。不能混用数据指针和函数指针。
    • @BodoThiesen 啊,你是对的;删除我答案的 C 部分,尽管他说他严格使用 C++
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-03
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多