你误会used attribute
二手
附加到函数的这个属性意味着必须为该函数发出代码,即使看起来该函数没有被引用...
即编译器必须发出函数定义,即使函数出现
不被引用。编译器永远不会断定一个函数是未引用的
如果它有外部链接。所以在这个程序中:
main1.c
static void foo(void){}
int main(void)
{
return 0;
}
编译:
$ gcc -c -O1 main1.c
根本没有发出foo 的定义:
$ nm main1.o
0000000000000000 T main
因为foo在翻译单元中没有被引用,不是外部的,
所以可能会被优化出来。
但是在这个程序中:
main2.c
static void __attribute__((used)) foo(void){}
int main(void)
{
return 0;
}
__attribute__((used)) 强制编译器发出本地定义:
$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main
但这并不能阻止 链接器 丢弃一个部分
其中定义了foo,在存在-gc-sections 的情况下,即使foo 是外部的,如果该部分未使用:
main3.c
void foo(void){}
int main(void)
{
return 0;
}
使用功能部分编译:
$ gcc -c -ffunction-sections -O1 main3.c
foo 的全局定义在目标文件中:
$ nm main3.o
0000000000000000 T foo
0000000000000000 T main
但链接后:
$ gcc -Wl,-gc-sections,-Map=mapfile main3.o
foo 没有在程序中定义:
$ nm a.out | grep foo; echo Done
Done
定义foo的函数部分被丢弃:
地图文件
...
...
Discarded input sections
...
...
.text.foo 0x0000000000000000 0x1 main3.o
...
...
根据 Eric Postpischil 的评论,强制 链接器 保留
一个明显未使用的功能部分,您必须告诉它假设该程序
引用未使用的函数,带有链接器选项{-u|--undefined} foo:
main4.c
void __attribute__((section(".mySec"))) foo(void){}
int main(void)
{
return 0;
}
如果你不告诉它:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done
foo 未在程序中定义。如果你告诉它:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done
它被定义了。属性 used 没有用处。