有没有一种方法可以忽略未使用的未定义引用?

7
假设我有两个源文件 — UndefErr.cpp
#include <cstdio>

void UndefFunc();
void Func2(){UndefFunc();}

void Func1(){printf("Hi\n");}

以下是主要内容main.cpp:

void Func1();

int main(){
    Func1();
    return 0;
}

您可以在 UndefErr.cpp 中看到, Func2()将触发错误,因为它使用未定义的 UndefFunc()。但是主函数并不关心 Func2()! 根据相关问题,我可以向链接器传递一个选项 --unresolved-symbols = ignore-in-object-files ,但我需要一种有点不同的东西。我需要链接器知道是否在某处使用了未定义的函数,仅在此情况下失败。
提出这样奇怪的问题的原因是我正在尝试使用 lwIP ,很难理解其所有依赖项(我只需要TCP / IP),我找不到互联网上的教程。 因此,我认为可以单独编译大多数(或全部) .c文件,并编写一些简单的测试以查看其功能。 但这种方法会遇到“未定义引用”,其中大部分可能与用例无关。

似乎链接器可以“找出”是否需要解析引用...但一个解决方案是,如果函数不多,使其变得繁琐,你可以在main.cpp中将它们存根起来...例如:void UndefFunc() {} - mark
@mark 不,这个项目有很多函数。而且主要问题是我不知道哪些函数没有被使用,所以我想要自动化一下。 - Hi-Angel
我不明白这个问题。如果链接器遇到未定义的函数,它会报错。 - BЈовић
@BЈовић,是的,但如果未定义的函数未被使用,忽略它可能更有意义。如何忽略这样的引用只是一个问题。 - Hi-Angel
2个回答

5

使用Gcc 4.8.2,我成功地链接了以下代码,没有出现错误:

$ g++ -c main.cpp -O3 -flto
$ g++ -c UndefErr.cpp -O3 -flto
$ g++ main.o UndefErr.o -flto -O3 -o out

我知道-flto会使链接器的行为就像传递了-fwhole-program并且整个程序是一个单一编译单元一样。而根据手册,-fwhole-program对应于在函数上使用static的正确用法,所以可以消除未使用的函数(即您确保编译器所有函数都不会被其他代码使用(可能是动态加载的),并且您向用户保证的唯一入口点是main())。
我必须添加-O3,但不确定原因是什么,但是没有它,编译器对于检查函数和消除死代码不太感兴趣。

太好了,我从未知道有这个选项!是的,在编译时不传递 -O3,由于某种原因,链接器拒绝中止未使用的函数。 - Hi-Angel
1
通过使用MSYS2 MinGW GCC 5.3.0版本构建,我成功地消除了未使用的函数,并通过-flto -Og编译器选项避免了与这些函数相关联的符号的“未定义引用”错误。 - Richard Lang

3
问题在于你使用了未定义的函数is。针对Func2的对象代码已经生成,但是存在对不存在的UndefFunc的引用,然后传递给链接器。编译器无法理解这个函数将始终未定义,因为有多个翻译单元。
避免编译错误的唯一方法是告诉链接器你不需要未使用的函数的对象代码,这样它就不会尝试为此情况生成汇编代码。

1
我已经搜索过了,发现可能需要两个东西:使用-fdata-sections -ffunction-sections作为标志,以便每个函数都在自己的部分中(允许链接器查看部分之间的引用),然后链接器需要知道确切的函数(在我的情况下是main),从而跟踪引用。 我还发现LD有一种脚本语言,所以我似乎可以在这里找到答案--似乎没有标准方法可以实现我想要的。 - Hi-Angel
我认为值得一提的是,在上述情况下,我应该从_start函数开始跟踪,因为它是第一个要执行的函数。否则,我可能会得到一个无法正常运行的可执行文件。 - Hi-Angel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接