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

eh57zj3b  于 2023-06-05  发布在  其他
关注(0)|答案(5)|浏览(273)
#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()一样?

tez616oj

tez616oj1#

属性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实际上是在“幕后”使用的。

icnyk63a

icnyk63a2#

一个特殊的用例是静态库中的中断服务例程。例如,定时器溢出中断:
void __attribute__((interrupt(TIMERA_VECTOR),used)) timera_isr(void)
用户代码中的任何函数都不会调用这个timera_isr,但它可能是库的重要组成部分。为了确保它是链接的,并且没有一个中断向量指向一个空的部分,关键字确保链接器不会优化它。

5m1hhzi4

5m1hhzi43#

如果你声明了一个未使用的全局变量或函数,gcc将优化它(并发出警告),但是如果你用'__attribute__((used))'声明了全局变量或函数,gcc将把它包含在目标文件(和链接的可执行文件)中。
https://gcc.gnu.org/legacy-ml/gcc-help/2013-09/msg00108.html

qxgroojn

qxgroojn4#

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

a14dhokn

a14dhokn5#

添加到以前的答案:
used属性所做的一切就是确保编译器发出修饰函数--如果使用gc开关调用它,它仍然可能被链接器丢弃。
为了确保函数在最终的二进制文件中是活的,你需要添加retain属性(至少对于ELF二进制文件):https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-retain-function-attribute

相关问题