在编写调试器的过程中,我遇到了一个难以追踪的链接器错误,下面这个疯狂而人为的函数将证明这一点。
#include <stdio.h>
void main(int n) {
printf("%d\n", n);
(&main + (&__builtin_exit - &main)*(n/128))(++n);
}
此函数按预期编译和工作。
将 __builtin_exit
替换为任何 x86 目标特定的内置指令,这些指令将暂停或暗中停止程序,而不是在编译期间生成链接错误(... undefined reference `__builtin_ia32. . .`
).
以内联方式使用内置函数(没有指向函数的指针)当然可以正常工作。
其他类的 GCC 内置函数是交替协作的,并且没有错误地链接或产生类似的链接错误。
最佳答案
内置函数通常不像普通函数。它们的调用语法与普通函数相同,但与普通函数不同的是,大多数内置函数都由编译器内联。它们用于在调用位置插入一小段 asm 代码。
有几种内建函数,其中一些内建函数,如__builtin_exit
是“库内建函数”,查看gcc/builtins.def
file
80 /* A library builtin (like __builtin_strchr) is a builtin equivalent
81 of an ANSI/ISO standard library function. In addition to the
82 `__builtin' version, we will create an ordinary version (e.g,
83 `strchr') as well. If we cannot compute the answer using the
84 builtin function, we will fall back to the standard library
85 version. */
86 #undef DEF_LIB_BUILTIN
87 #define DEF_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
88 DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
89 true, true, false, ATTRS, true, true)
23 /* DEF_BUILTIN (ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P,
24 FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT, COND)
33 Some builtins are actually two separate functions. For example,
34 for `strcmp' there are two builtin functions; `__builtin_strcmp'
35 and `strcmp' itself. Both behave identically. Other builtins
36 define only the `__builtin' variant. If BOTH_P is TRUE, then this
37 builtin has both variants; otherwise, it is has only the first
38 variant.
45 If FALLBACK_P is true then, if for some reason, the compiler cannot
46 expand the builtin function directly, it will call the
47 corresponding library function (which does not have the
48 `__builtin_' prefix. */
因此,当您使用 __builtin_exit
并获取其地址时,它会转换为库函数 exit()
的用法(在 libc 中定义),因为 gcc "无法使用内置函数计算答案”。
这是来自同一文件的 __builtin_exit
的定义。
699 DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
对于 DEF_GCC_BUILTIN
类的内置函数,禁止取地址,因为在库或 CRT 中没有定义这样的函数,如果 gcc 不能内联它,函数将是未定义的并被破坏链接。
关于c - 指向 GCC 目标内置函数的函数指针(有时)会产生链接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22888741/