gcc used 属性的用例是什么?
What's the usecase of gcc's used attribute?
#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's documentation 所说(强调我的):
This attribute, attached to a function, means that code must be
emitted for the function even if it appears that the function is not
referenced. This is useful, for example, when the function is
referenced only in inline assembly.
例如,如果您有如下代码:
#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
确实被使用 "behind the scene".
一个特定的用例是静态库中的中断服务例程。
比如定时器溢出中断:
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))
标记您的函数。
#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's documentation 所说(强调我的):
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.
例如,如果您有如下代码:
#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
确实被使用 "behind the scene".
一个特定的用例是静态库中的中断服务例程。 比如定时器溢出中断:
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))
标记您的函数。