在C(gcc)中获取指向当前函数的指针?
gcc中有一个魔术变量,它持有一个指向当前函数的指针吗?
我想有一种表包含每个函数指针的一组信息。
我知道有一个__func__变量包含当前函数的名称作为字符串但不作为函数指针。
这不是为了调用函数而是仅仅用作索引。
编辑基本上我想做的是能够在执行当前函数之前运行嵌套函数(并且还捕获返回以执行某些操作。)基本上,这就像__cyg_profile_func_enter和__cyg_profile_func_exit(检测函数)。但问题是这些仪器function是全局的而不是function专用的。
编辑在linux内核中,您可以使用include/linux/kallsyms.h
unsigned long kallsyms_lookup_name(const char *name)
…请注意,必须激活CONFIG_KALLSYMS
选项。
这是一个获取调用者地址的技巧,它可能会被清理一下。 依靠GCC扩展来获取标签的价值 。
#include #define MKLABEL2(x) label ## x #define MKLABEL(x) MKLABEL2(x) #define CALLFOO do { MKLABEL(__LINE__): foo(&&MKLABEL(__LINE__));} while(0) void foo(void *addr) { printf("Caller address %p\n", addr); } int main(int argc, char **argv) { CALLFOO; return 0; }
void f() { void (*fpointer)() = &f; }
#define FUNC_ADDR (dlsym(dlopen(NULL, RTLD_NOW), __func__))
并编译你的程序
gcc -rdynamic -o foo foo.c -ldl
我认为您可以使用字符串(函数名称)作为键来构建表,然后通过与__func__
内置变量进行比较来__func__
。
要强制使用有效的函数名,可以使用获取函数指针的宏,对其执行一些虚拟操作(例如,将其分配给兼容的函数类型临时变量)以检查它是否确实是有效的函数标识符,然后进行字符串化(用#)作为键之前的函数名。
更新:
我的意思是:
typedef struct { char[MAX_FUNC_NAME_LENGTH] func_name; //rest of the info here } func_info; func_info table[N_FUNCS]; #define CHECK_AND_GET_FUNC_NAME(f) ({void (*tmp)(int); tmp = f; #f}) void fill_it() { int i = -1; strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(foo)); strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(bar)); //fill the rest } void lookup(char *name) { int i = -1; while(strcmp(name, table[++i])); //now i points to your entry, do whatever you need } void foo(int arg) { lookup(__func__); //do something } void bar(int arg) { lookup(__func__); //do something }
(代码可能需要一些修复,我还没有尝试编译它,它只是为了说明这个想法)
如果您使用C ++,以下信息可能对您有所帮助:
对象是类型化的, 仿函数是包装为对象的函数, RTTI允许在运行时识别类型。
Functors带有运行时开销,如果这对你来说是一个问题我会建议使用代码生成来硬编码知识或利用仿函数的OO-heirarchy。
不,该function不了解自己。 您将不得不构建您自己正在讨论的表,然后如果您希望函数知道自己,则必须将索引作为参数传递给全局表(或函数的指针)。
注意:如果要执行此操作,则应该具有一致的参数命名方案。
如果你想以’通用’的方式做这件事,那么你应该使用你已经提到的设施( __cyg_profile_func*
),因为这是它们的设计目的。 其他任何东西都必须像你的个人资料一样临时。
老实说,以通用方式(使用filter)执行操作可能比您将即时插入的任何新方法更不容易出错。
您可以使用setjmp()
捕获此信息。 由于它保存了足够的信息以返回当前函数,因此必须在提供的jmp_buf
包含该信息。
这种结构是非常不可移植的,但是你明确地提到了GCC,这可能不是阻塞问题。 请参阅此GCC / x86示例,以了解它是如何工作的。
如果你想做代码生成,我会从Imatix推荐GSLGen。 它使用XML来构建代码模型,然后使用简单的PHP(如自上而下的生成语言)来吐出代码 – 它已被用于生成C代码。
我个人一直在玩lua来生成代码。
static const char * const cookie = __FUNCTION__;
__FUNCTION__
将存储在二进制文件的文本段中,指针始终是唯一且有效的。
另一个选择,如果可移植性不是问题,那就是调整GCC源代码……任何志愿者?!
如果你需要的只是每个函数的唯一标识符,那么在每个函数的开头,把它放在:
static const void * const cookie = &cookie;
然后, cookie
的值保证是唯一标识该函数的值。