GCC可以不抱怨未定义的引用吗?

尝试调用组合函数时,GCC在什么情况下不能抛出“未定义的引用”链接错误消息?

例如,这个C代码被GCC编译和链接的情况:

void function() { made_up_function_name(); return; } 

即使made_up_function_name不存在于代码中的任何地方 (不是头文件,源文件,声明或任何第三方库)。

GCC可以在一定条件下接受和编译这样的代码,而不必触摸实际的代码? 如果是这样,哪个?

谢谢。

编辑:没有以前的声明或提到made_up_function_name是否在其他地方。 这意味着整个文件系统的grep -R显示确切的单行代码。

是的,可以避免报告未定义的引用 – 使用--unresolved-symbols链接器选项。

 g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files 

man ld

–unresolved符号=方法

确定如何处理未解决的符号。 方法有四种可能的值:

  ignore-all Do not report any unresolved symbols. report-all Report all unresolved symbols. This is the default. ignore-in-object-files Report unresolved symbols that are contained in shared libraries, but ignore them if they come from regular object files. ignore-in-shared-libs Report unresolved symbols that come from regular object files, but ignore them if they come from shared libraries. This can be useful when creating a dynamic binary and it is known that all the shared libraries that it should be referencing are included on the linker's command line. 

共享库本身的行为也可以通过 – [no-] allow-shlib-undefined选项来控制。

通常,链接器将为每个报告的未parsing符号生成错误消息,但是选项–warn-unresolved-symbols可以将其更改为警告。

如果你在使用函数之前声明函数的原型,那么它就会编译。 无论如何,链接时的错误仍然存​​在。

 void made_up_function_name(); void function() { made_up_function_name(); return; } 

如果function()永远不会被调用,它可能不会被包含在可执行文件中,并且从它调用的函数也不会被search。

TL; DR它不能抱怨,但你不想这样做 。 如果您强制链接器忽略该问题,您的代码将崩溃。 这会适得其反。

您的代码依赖于古老的C(C99之前版本),允许在使用时隐式声明函数。 您的代码在语义上等同于以下代码:

 void function() { int made_up_function_name(...); // The implicit declaration made_up_function_name(); // Call the function return; } 

链接器正确地抱怨包含编译的function()的目标文件是指在其他地方找不到的符号。 您必须通过提供 made_up_function_name() 的实现 或删除无意义的调用来修复它。 这就是它的全部。 没有链接器 – 摆弄。

当你使用连接器标志-r--relocatable构build时,它也不会产生任何“未定义的引用”链接错误消息。

这是因为-r会链接新对象文件中的不同对象,以便在稍后阶段进行链接。

然后,这个传递给GCC的-D标志就是这样的混乱。

 $cat undefined.c void function() { made_up_function_name(); return; } int main(){ } $gcc undefined.c -Dmade_up_function_name=atexit $ 

想象一下寻找made_up_function_name的定义 – 它在代码中看起来还没有“做事”。 我想不出一个很好的理由在代码中做这个确切的事情。

-D标志是在编译时更改代码的强大工具。

POSIX链接器所使用的“标准”algorithm使得代码编译和链接的可能性没有任何错误。 详情请看这里: https : //stackoverflow.com/a/11894098/187690

为了利用这种可能性,包含你的function的对象文件(我们称之为fo )应该放在一个库中。 应该在编译器(和/或链接器)的命令行中提到这个库,但到那时为止,没有其他的对象文件(在前面提到的命令行中)应该已经调用了functionfo存在的任何其他函数。 在这种情况下,链接器将没有任何理由从图书馆中取回。 链接器将完全忽略fo ,完全忽略function ,因此完全忽略了对made_up_function_name的调用。 即使made_up_function_name没有在任何地方定义,代码也会被编译。