确定指针指向C的函数?

Sum*_*mit 53 c function-pointers

我有一个指向函数的指针,假设有任何签名.我有5个不同的功能和相同的签名.

在运行时,其中一个被分配给指针,并调用该函数.

如果不在这些函数中插入任何print语句,我怎样才能知道指针当前指向的函数名称?

nos*_*nos 65

您必须检查指针指向的5个函数中的哪一个:

if (func_ptr == my_function1) {
    puts("func_ptr points to my_function1");
} else if (func_ptr == my_function2) {
    puts("func_ptr points to my_function2");
} else if (func_ptr == my_function3) {
    puts("func_ptr points to my_function3");
} ... 
Run Code Online (Sandbox Code Playgroud)

如果这是您需要的常见模式,则使用结构表而不是函数指针:

typedef void (*my_func)(int);

struct Function {
    my_func func;
    const char *func_name;
};

#define FUNC_ENTRY(function) {function, #function}

const Function func_table[] = {
    FUNC_ENTRY(function1),
    FUNC_ENTRY(function2),
    FUNC_ENTRY(function3),
    FUNC_ENTRY(function4),
    FUNC_ENTRY(function5)
}

struct Function *func = &func_table[3]; //instead of func_ptr = function4;

printf("Calling function %s\n", func->func_name);
func ->func(44); //instead of func_ptr(44);
Run Code Online (Sandbox Code Playgroud)


jan*_*neb 27

通常,在C中,程序员无法使用这些东西.

通过使用调试符号等可能有系统特定的方法到达那里,但您可能不希望依赖于这些方法的存在以使程序正常运行.

但是,您当然可以将指针的值与另一个值进行比较,例如

if (ptr_to_function == some_function)
    printf("Function pointer now points to some_function!\n");
Run Code Online (Sandbox Code Playgroud)

  • @Lundin,这是一个预处理程序指令,它获取当前具有作用域的函数的当前名称,甚至不能远程应用于该问题. (11认同)
  • @Lundin但是不仅仅是在函数的*body*中可用吗?OP希望单独从'ptr_to_function`中找到名称. (10认同)
  • 在C中,程序员通过`__func__`标识符实际可以使用这些东西. (3认同)
  • @Sam`__func__`只在函数中可用,因此这里不是一个好的答案,但它是一个普通的(确切地说,TP7)标识符,不是像`__FILE__`和`__LINE__`这样的预处理器宏,也不是像``_ #if`. (3认同)

Bat*_*eba 16

函数名称在运行时将不可用.

C不是反思语言.

维护由其名称键入的函数指针表,或提供调用返回名称的每个函数的模式.

  • *反射*是我失踪的词.奖励! (2认同)

Bas*_*tch 15

调试器可以告诉你(即函数的名称,给定其地址).

未提取的ELF可执行文件的符号表也可以提供帮助.见nm(1),objdump(1),readelf(1)

另一种Linux GNU/libc特定的方法可能是在运行时使用dladdr(3)函数.假设您的程序很好地动态链接(例如-rdynamic),它可以找到符号名称和共享对象路径给定一些地址(全局命名的函数).

当然,如果您只有给定签名的五个函数,则可以比较您的地址(到它们的五个地址).

请注意,某些函数没有任何((全局可见)名称,例如static函数.

并且可以对一些函数进行dlopen-ed和dlsym-ed(例如在插件内部).或者他们的代码被一些JIT-ING框架(在运行时synthetized libjit,gccjit,LLVM,asmjit).并且优化编译器可以(并且确实!)内联函数,克隆它们,尾随它们等等....所以你的问题一般没有任何意义......

另请参阅回溯(3)和Ian Taylor 在GCC中的libbacktrace.

但总的来说,你的追求是不可能的.如果您确实需要可靠的反馈信息,请自行管理(以Pitrat的CAIA系统为例,或以某种方式查看我的MELT系统),或许可以在构建过程中生成一些代码.


Lun*_*din 13

要知道函数指针指向的位置,您必须跟踪程序.最常见的是声明一个函数指针数组,并使用int变量作为此数组的索引.

话虽如此,现在也可以通过使用__func__标识符在运行时告诉当前执行哪个函数:

#include <stdio.h>

typedef const char* func_t (void);

const char* foo (void)
{
  // do foo stuff
  return __func__;
}

const char* bar (void)
{
  // do bar stuff
  return __func__;
}

int main (void)
{
  func_t* fptr;

  fptr = foo;
  printf("%s executed\n", fptr());

  fptr = bar;
  printf("%s executed\n", fptr());

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

foo executed
bar executed
Run Code Online (Sandbox Code Playgroud)

  • 这类似于在函数中放置一个print语句.我接受了这个限制意味着你无法修改函数内部的代码. (7认同)

Mar*_*ler 10

完全没有 - 编译后函数的符号名称消失了.与反射语言不同,C不知道程序员如何命名其语法元素; 特别是,编译后没有名称的"函数查找".

您当然可以拥有一个函数指针的"数据库"(例如数组),您可以将当前指针与之进行比较.

  • @Lundin只在函数中,所以你必须为每个函数添加代码以"调用"它并让它返回名称,或者你可以做一些hacky内存扫描来查找函数名.无论哪种方式,它都不会简单. (5认同)

R..*_*R.. 8

这非常糟糕且不便携,但假设:

  1. 您使用的是Linux或类似的基于ELF的系统.
  2. 您正在使用动态链接.
  3. 该函数位于共享库中,或者-rdynamic在链接时使用.
  4. 可能还有很多其他的假设你不应该......

您可以通过将其地址传递给非标准dladdr函数来获取函数的名称.