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