GCC 不能抱怨未定义的引用吗?
在什么情况下,GCC 在尝试调用虚构函数时可能不抛出“未定义引用”链接错误消息?
例如,此 C 代码由 GCC 编译和链接的情况:
void function()
{
made_up_function_name();
return;
}
...即使 made_up_function_name
不存在于代码中任何地方(不是标头、源文件) 、声明或任何第三方库)。
在某些条件下,这种代码是否可以被 GCC 接受并编译,而无需触及实际代码?如果有,是哪一个?
谢谢。
编辑:其他任何地方都没有先前的声明或提及 made_up_function_name
。这意味着整个文件系统的 grep -R
将仅显示确切的单行代码。
Under what situation is it possible for GCC to not throw an "undefined reference" link error message when trying to call made-up functions?
For example, a situation in which this C code is compiled and linked by GCC:
void function()
{
made_up_function_name();
return;
}
...even though made_up_function_name
is not present anywhere in the code (not headers, source files, declarations, nor any third party library).
Can that kind of code be accepted and compiled by GCC under certain conditions, without touching the actual code? If so, which?
Thanks.
EDIT: no previous declarations or mentions to made_up_function_name
are present anywhere else. Meaning that a grep -R
of the whole filesystem will only show that exact single line of code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
是的,可以使用
--unresolved-symbols
链接器选项来避免报告未定义的引用。来自
man ld
Yes, it is possible to avoid reporting undefined references - using
--unresolved-symbols
linker option.From
man ld
如果在使用函数之前声明函数的原型,则它应该编译。无论如何,链接时的错误仍然存在。
If you declare the prototype of the function before using it , it shold compile. Anyway the error while linking will remain.
TL;DR它不能抱怨,但你不想要这样。如果您强制链接器忽略该问题,您的代码将会崩溃。这会适得其反。
您的代码依赖于古老的 C(C99 之前的版本),允许在使用时隐式声明函数。您的代码在语义上与以下代码相同:
链接器正确地抱怨包含已编译
function()
的目标文件引用了在其他地方找不到的符号。您必须通过提供made_up_function_name()
的实现或删除无意义的调用来修复它。这就是全部内容了。不涉及链接器摆弄。TL;DR It can not complain, but you don't want that. Your code will crash if you force the linker to ignore the problem. It'd be counterproductive.
Your code relies on the ancient C (pre-C99) allowing functions to be implicitly declared at their point of use. Your code is semantically equivalent to the following code:
The linker rightfully complains that the object file that contains the compiled
function()
refers to a symbol that wasn't found anywhere else. You have to fix it by providing the implementation formade_up_function_name()
or by removing the nonsensical call. That's all there's to it. No linker-fiddling involved.当您使用链接器标志
-r
或--relocatable
进行构建时,它也不会产生任何“未定义的引用”链接错误消息。这是因为
-r
将链接新对象文件中的不同对象,以便稍后链接。When you build with the linker flag
-r
or--relocatable
it will also not produce any "undefined reference" link error messages.This is because
-r
will link different objects in a new object file to be linked at a later stage.然后,-D 标志传递给 GCC 时就会出现这种令人讨厌的情况。
想象一下寻找 made_up_function_name 的定义——它在代码中还没有出现“做事”。
我想不出在代码中执行此操作的好理由。
-D 标志是在编译时更改代码的强大工具。
And then there is this nastiness with the -D flag passed to GCC.
Just imagine looking for the definition of made_up_function_name- it appears nowhere yet "does things" in the code.
I can't think of a nice reason to do this exact thing in code.
The -D flag is a powerful tool for changing code at compile time.
如果
function()
从未被调用,它可能不会包含在可执行文件中,并且也不会搜索从中调用的函数。If
function()
is never called, it might not be included in the executable, and the function called from it is not searched for either.POSIX 链接器操作所依据的“标准”算法使得代码编译和链接没有任何错误的可能性成为可能。有关详细信息,请参阅此处: https://stackoverflow.com/a/11894098/187690
为了利用该对象的可能性包含您的
函数
(我们称之为fo
)的文件应放入库中。该库应该在编译器(和/或链接器)的命令行中提及,但此时没有其他目标文件(在命令行中前面提到过)应该对function
或fo
中存在的任何其他函数。在这种情况下,链接器将认为没有理由从库中检索fo
。链接器将完全忽略fo
,完全忽略function
,因此完全忽略对made_up_function_name
的调用。即使made_up_function_name
没有在任何地方定义,代码也会编译。The "standard" algorithm according to which POSIX linkers operate leaves open the possibility that the code will compile and link without any errors. See here for details: https://stackoverflow.com/a/11894098/187690
In order to exploit that possibility the object file that contains your
function
(let's call itf.o
) should be placed into a library. That library should be mentioned in the command line of the compiler (and/or linker), but by that moment no other object file (mentioned earlier in the command line) should have made any calls tofunction
or any other function present inf.o
. Under such circumstances linker will see no reason to retrievef.o
from the library. Linker will completely ignoref.o
, completely ignorefunction
and, therefore, remain completely oblivious of the call tomade_up_function_name
. The code will compile even thoughmade_up_function_name
is not defined anywhere.