在什么情况下GCC可能会不在尝试调用假装函数时抛出“未定义的引用”链接错误消息?
例如,GCC编译和链接此C代码的情况:
void function()
{
made_up_function_name();
return;
}
...即使made_up_function_name
在代码中不存在任何地方(不是标题,源文件,声明或任何第三方库)。
GCC是否可以在某些条件下接受和编译这种代码,而无需触及实际代码?如果是这样,哪个?
感谢。
编辑:以前没有任何声明或提及made_up_function_name
。这意味着整个文件系统的grep -R
将仅显示完整的单行代码。
答案 0 :(得分:82)
是的,可以使用--unresolved-symbols
链接器选项来避免报告未定义的引用。
g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files
来自man ld
<强> - 未解决的符号=方式
确定如何处理未解析的符号。有四个 方法的可能值:
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选项控制。
通常,链接器会为每个链接生成错误消息 报告未解决的符号,但选项--warn-unresolved-symbols可以 将此更改为警告。
答案 1 :(得分:3)
如果在使用之前声明函数的原型,那么它就会编译。无论如何,链接时的错误仍然存在。
void made_up_function_name();
void function()
{
made_up_function_name();
return;
}
答案 2 :(得分:2)
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()
提供实施或删除无意义的通话来解决此问题。这就是它的全部内容。没有涉及链接器的小提琴。
答案 3 :(得分:1)
如果永远不会调用function()
,它可能不会包含在可执行文件中,也不会搜索从它调用的函数。
答案 4 :(得分:1)
然后将-D标志传递给GCC就会出现这种肮脏现象。
$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标志是一个在编译时更改代码的强大工具。
答案 5 :(得分:1)
使用链接器标志-r
或--relocatable
构建时,它也不会产生任何“未定义的引用”链接错误消息。
这是因为-r
将链接新目标文件中的不同对象,以便在以后链接。
答案 6 :(得分:0)
&#34;标准&#34;根据POSIX链接器操作的算法留下了开放代码编译和链接没有任何错误的可能性。有关详细信息,请参阅此处:https://stackoverflow.com/a/11894098/187690
为了利用这种可能性,应将包含function
(让我们称之为f.o
)的目标文件放入库中。应该在编译器(和/或链接器)的命令行中提到该库,但到那时,没有其他目标文件(在命令行中先前提到)应该对function
或任何其他函数进行任何调用出现在f.o
。在这种情况下,链接器将没有理由从库中检索f.o
。链接器将完全忽略f.o
,完全忽略function
,因此完全忽略了对made_up_function_name
的调用。即使made_up_function_name
未在任何地方定义,代码也会编译。