提问人:Post Self 提问时间:1/30/2023 最后编辑:John BollingerPost Self 更新时间:1/30/2023 访问量:119
通过剥离未使用的代码来解析未定义的引用
Resolve undefined reference by stripping unused code
问:
假设我们有以下 C 代码:
void undefined_reference(void);
void bad(void) {
undefined_reference();
}
int main(void) {}
在功能中,我们陷入了 链接器错误 ,正如预期的那样。但是,此函数实际上并未在代码中的任何位置使用,因此,对于程序的执行,此未定义的引用无关紧要。bad
undefined reference to 'undefined_reference'
是否有可能成功编译此代码,以便简单地将其删除,因为它从未被调用(类似于 JavaScript 中的摇树)?bad
答:
2赞
0___________
1/30/2023
#1
许多编译器(例如 gcc)会正确编译和链接它,如果你
- 启用优化
- make 函数。否则,它将具有外部链接。
bad
static
https://godbolt.org/z/KrvfrYYdn
另一种方法是添加此函数的 stump 版本(以及显示警告的编译指示)
评论
0赞
Eugene Sh.
1/30/2023
不过,我不会在生产代码中依赖它......
0赞
0___________
1/30/2023
@EugeneSh。我也是。。。。
3赞
John Bollinger
1/30/2023
但是,如果还不是静态的,那么这需要修改源代码,如果您愿意并且能够这样做,那么您不妨完全删除该函数或通过条件编译指令取消其定义。bad()
4赞
n. m. could be an AI
1/30/2023
#2
这个函数实际上并没有在代码中的任何位置使用!
你知道,我知道,但编译器不知道。它一次处理一个翻译单元。它不能说没有其他翻译单位。
但是 main
不调用任何东西,所以不能有其他翻译单元!
可以有在之前和之后运行的代码(以实现定义的方式)。main
好的,链接器呢?它可以看到整个程序!
没有。代码可以在运行时动态加载(也可以通过链接器看不到的代码加载)。
因此,默认情况下,编译器和链接器甚至都不会尝试查找未使用的函数。
在某些系统上,可以指示编译器和链接器尝试对未使用的代码进行垃圾回收(并在这样做时假定整个程序视图),但这通常不是默认的操作模式。
使用 gcc 和 gnu ld,您可以使用以下选项:
gcc -ffunction-sections -Wl,--gc-sections main.c -o main
其他系统可能有不同的方法来执行此操作。
评论
0赞
Eugene Sh.
1/30/2023
在大多数情况下,链接器能够消除未使用的部分。我不确定这里的默认值是什么,但它也能够将每个函数放在一个单独的部分中(实际上,编译器可以)。因此,有了这两个能力,它可以(并且将)消除未使用的功能。
1赞
n. m. could be an AI
1/30/2023
@EugeneSh。添加了启用此行为的选项。
评论
undefined_reference
bad
bad
undefined_reference()
bad()