#include <stdio.h>
// xyz will be emitted with -flto (or if it is static) even when
// the function is unused
__attribute__((__used__))
void xyz() {
printf("Hello World!\n");
}
int main() {
return 0;
}
我要这个干什么?
除了直接调用函数之外,还有什么方法可以达到xyz
,就像一些dlsym()
一样?
5条答案
按热度按时间tez616oj1#
属性
used
在你想强制编译器发出符号的情况下很有用,通常它可以被省略。正如GCC的文档所说(强调我的):附加到函数的此属性意味着必须为该函数发出代码,即使该函数似乎未被引用。这很有用,例如,当函数仅在内联程序集中被引用时。
例如,如果你有如下代码:
您可能会注意到,没有符号
foo
存在-O
标志(优化级别-O1
):因此,您无法在此(假想的)内联程序集中引用
foo
。加入:
它就变成了:
因此现在可以在其中引用
foo
。您可能还发现
gcc
的警告现在已经消失了,因为您已经告诉编译器您确信foo
实际上是在“幕后”使用的。icnyk63a2#
一个特殊的用例是静态库中的中断服务例程。例如,定时器溢出中断:
void __attribute__((interrupt(TIMERA_VECTOR),used)) timera_isr(void)
用户代码中的任何函数都不会调用这个timera_isr,但它可能是库的重要组成部分。为了确保它是链接的,并且没有一个中断向量指向一个空的部分,关键字确保链接器不会优化它。
5m1hhzi43#
如果你声明了一个未使用的全局变量或函数,gcc将优化它(并发出警告),但是如果你用
'__attribute__((used))'
声明了全局变量或函数,gcc将把它包含在目标文件(和链接的可执行文件)中。https://gcc.gnu.org/legacy-ml/gcc-help/2013-09/msg00108.html
qxgroojn4#
另一个用例是为头文件生成适当的覆盖率信息。在头文件中声明的函数在未引用时通常会被编译器删除。因此,即使您忘记调用位于头文件中的某些函数,您也会在覆盖率报告中获得100%的覆盖率。为了防止这种情况,您可以在覆盖构建中使用
__attribute__((used))
标记您的函数。a14dhokn5#
添加到以前的答案:
used
属性所做的一切就是确保编译器发出修饰函数--如果使用gc开关调用它,它仍然可能被链接器丢弃。为了确保函数在最终的二进制文件中是活的,你需要添加
retain
属性(至少对于ELF二进制文件):https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-retain-function-attribute