gcc中有一个魔术变量,它持有一个指向当前函数的指针吗?
我想有一种表包含每个函数指针的一组信息。
我知道有一个__func__变量包含当前函数的名称作为字符串但不作为函数指针。
这不是为了调用函数而是仅仅用作索引。
编辑
基本上我想做的是能够在执行当前函数之前运行嵌套函数(并且还捕获返回以执行某些操作。)
基本上,这就像__cyg_profile_func_enter和__cyg_profile_func_exit(检测功能)......但问题是这些检测功能是全局的而不是功能专用的。
编辑
在linux内核中,您可以使用 unsigned long kallsyms_lookup_name(const char *name)
从 include/linux/kallsyms.h
...注意 CONFIG_KALLSYMS
必须激活选项。
这是一个获取调用者地址的技巧,它可能会被清理一下。
依赖于 用于获取标签价值的GCC扩展。
#include <stdio.h>
#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__
内置变量。
要强制使用有效的函数名,可以使用获取函数指针的宏,对其执行一些虚拟操作(例如,将其分配给兼容的函数类型临时变量)以检查它是否确实是有效的函数标识符,然后进行字符串化(用#)作为键之前的函数名。
更新:
我的意思是:
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。
不,该功能不了解自己。您将不得不构建您自己正在讨论的表,然后如果您希望函数知道自己,则必须将索引作为参数传递给全局表(或函数的指针)。
注意:如果要执行此操作,则应该具有一致的参数命名方案。
如果你想以'通用'方式做到这一点,那么你应该使用你已经提到的设施(__cyg_profile_func*
)因为这是他们的目的。其他任何东西都必须像你的个人资料一样临时。
老实说,以通用方式(使用过滤器)执行操作可能比您将即时插入的任何新方法更不容易出错。
您可以使用捕获此信息 setjmp()
。由于它可以保存足够的信息以返回当前功能,因此必须在提供的信息中包含该信息 jmp_buf
。
这种结构是非常不可移植的,但是你明确地提到了GCC,这可能不是阻塞问题。看到 这个GCC / x86 例子来了解它是如何工作的。
如果你想做代码生成,我会建议 GSLGen 来自Imatix。它使用XML来构建代码模型,然后使用简单的PHP(如自上而下的生成语言)来吐出代码 - 它已被用于生成C代码。
我个人一直在玩lua来生成代码。