gcc 使用的属性的用例是什么?

What's the usecase of gcc's used attribute?

本文关键字:是什么 属性 gcc      更新时间:2023-10-16
#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()一样神奇吗?

属性used在你想强制编译器发出符号的情况下是有用的,通常情况下它可以被省略。正如GCC的文档所说(强调我的):

这个属性附加在函数上,意味着代码必须是为函数发出,即使函数似乎不是引用。这很有用,例如,当函数.

例如,如果代码如下:

#include <iostream>
static int foo(int a, int b)
{
    return a + b;
}
int main()
{
   int result = 0;
   // some inline assembly that calls foo and updates result
   std::cout << result << std::endl;
}

您可能会注意到,没有符号foo-O标志(优化级别-O1)一起出现:

g++ -O -pedantic -Wall check.cpp -c
check.cpp:3: warning: ‘int foo(int, int)’ defined but not used
nm check.o | c++filt | grep foo

因此不能在这个(假想的)内联程序集中引用foo

通过添加:

__attribute__((__used__))

变成:

g++ -O -pedantic -Wall check.cpp -c
nm check.o | c++filt | grep foo
00000000 t foo(int, int)

因此现在foo可以在其中被引用。

您可能还发现gcc的警告现在已经消失了,因为您已经告诉编译器您确信foo实际上是在"幕后"使用的。

一个特殊的用例是静态库中的中断服务例程。例如,定时器溢出中断:

void __attribute__((interrupt(TIMERA_VECTOR),used)) timera_isr(void)

这个timera_isr永远不会被用户代码中的任何函数调用,但它可能是库的重要组成部分。为了确保它被链接并且没有指向空部分的中断向量,关键字确保链接器不会优化它。

如果您声明的全局变量或函数是未使用的,gcc将对其进行优化(带有警告),但如果您使用'__attribute__((used))'声明全局变量或函数,gcc将将其包含在目标文件(和链接的可执行文件)中。

https://gcc.gnu.org/legacy-ml/gcc-help/2013-09/msg00108.html

另一个用例是为头文件生成适当的覆盖信息。在头文件中声明的函数在未被引用时通常会被编译器删除。因此,即使您忘记调用位于头文件中的一些函数,您也将在覆盖率报告中获得100%的覆盖率。为了防止这种情况,您可以在您的覆盖构建中用__attribute__((used))标记您的函数。

加上前面的答案:

所有used属性所做的是确保编译器发出修饰函数-如果它被gc开关调用,它仍然可能被链接器丢弃。

要确保函数在最终的二进制文件中是活动的,您需要添加retain属性(至少对于ELF二进制文件):https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-retain-function-attribute