确定指针在C中指向哪个函数?
我有一个指针function,假设任何签名。 我有5个不同的function相同的签名。
在运行时,其中的一个被分配到指针,并调用该函数。
如果不在这些函数中插入任何print语句,我怎么才能知道指针当前指向的函数的名字?
你将不得不检查你的指针所指向的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"); } ...
如果这是您需要的常见模式,则使用结构表而不是函数指针:
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);
一般来说,在C中,程序员不能使用这些东西。
通过使用debugging符号等可能会有系统特定的方法,但是您可能不希望依赖这些方法来使程序正常工作。
但是,您当然可以将指针的值与另一个值比较,例如
if (ptr_to_function == some_function) printf("Function pointer now points to some_function!\n");
函数名称在运行时不可用。
C不是reflection语言。
既可以维护一个按名称键入的函数指针表,也可以提供一个调用每个返回名称的函数的模式。
debugging器可以告诉你(即一个函数的名称,给出它的地址)。
UNTR可执行文件的符号表也可以提供帮助。 见nm(1) , objdump(1) , readelf(1)
另一个Linux GNU / libc特定的方法可以是在运行时使用dladdr(3)函数。 假设你的程序是很好地dynamic链接的(例如-rdynamic
),它可以find符号名称和共享对象path给定的地址(全局命名函数)。
当然,如果你只有一个给定签名的五个函数,你可以比较你的地址(它们的五个地址)。
请注意,一些函数没有任何((全局可见)名称,例如static
函数。
还有一些function可以是dlopen
-ed和dlsym
-ed(例如,内部插件)。 或者他们的代码在运行时通过一些JIT框架( libjit
, gccjit
, LLVM
, asmjit
)进行合成。 而且优化编译器可以(也可以)内联函数,克隆它们, 调用它们,等等……所以你的问题可能没有任何意义。
参见GCC里的backtrace(3)和Ian Taylor的libbacktrace 。
但总的来说,你的追求是不可能的。 如果你真的需要可靠的reflection信息,你可以自己pipe理(可以看看Pitrat的CAIA系统,或者我的MELT系统),也许在构build过程中生成一些代码。
要知道函数指针指向哪里,就必须跟踪程序。 最常见的是声明一个函数指针数组,并使用一个intvariables作为这个数组的索引。
也就是说,现在也可以通过使用__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; }
输出:
foo executed bar executed
一点也不 – 函数的符号名称在编译后就消失了。 与reflection语言不同,C不知道程序员如何命名它的语法元素; 特别是编译后没有名称的“函数查找”。
你当然可以有一个“数据库”(例如一个数组)的函数指针,你可以比较你的当前指针。
这是非常可怕和不可移植的,但假设:
- 您正在使用Linux或一些类似的基于ELF的系统。
- 您正在使用dynamic链接。
- 该函数在共享库中,或者在
-rdynamic
时使用了-rdynamic
。 - 也许很多其他的假设你不应该做…
您可以通过将其地址传递给非标准dladdr
函数来dladdr
函数的名称。
- 设置你的链接器输出一个MAP文件。
- 暂停程序
- 检查指针中包含的地址。
- 查看MAP文件中的地址,找出正在指向哪个函数。
指向C函数的指针就像任何指针一样是一个地址。 您可以从debugging器中获取该值。 您可以将指针转换为具有足够位数的任何整数types来完整地表示它,并将其打印出来。 任何可以使用指针的编译单元,即具有函数名称的函数名称,都可以打印指针值或将它们与运行时variables进行比较,而不必触摸函数内部的任何内容。