在编写调试器的过程中,我遇到了一个难以追踪的链接器错误,这个疯狂和人为的功能将会证明这一点。
#include <stdio.h>
void main(int n) {
printf("%d\n", n);
(&main + (&__builtin_exit - &main)*(n/128))(++n);
}
此功能可按预期编译和工作。
将__builtin_exit
替换为任何暂停或暗中暂停程序的x86目标特定内置指令,而不是在编译期间生成链接错误(...undefined reference to `__builtin_ia32. ..`
)。
以内联方式使用内置函数(没有指向函数的指针)当然可以正常工作。
GCC内置的其他类是备用协作和链接而没有错误或产生类似的链接错误。
答案 0 :(得分:3)
内置函数通常不像普通函数。它们以与普通函数相同的语法调用,但与普通函数不同,大多数内置函数都由编译器内联。它们用于在调用位置插入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无法内联它,则该函数将是未定义的并且会断开链接。 / p>