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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5555632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 08:16:39  来源:igfitidea点击:

Can GCC not complain about undefined references?

cgcccompiler-errorscompiler-warnings

提问by STenyaK

Under what situation is it possible for GCC to notthrow an "undefined reference" link error message when trying to call made-up functions?

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

For example, a situation in which this C code is compiled and linked by GCC:

比如这段C代码被GCC编译链接的情况:

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

...even though made_up_function_nameis not present anywherein the code (not headers, source files, declarations, nor any third party library).

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

Can that kind of code be accepted and compiled by GCC under certain conditions, without touching the actual code? If so, which?

那种代码可以在一定条件下被 GCC 接受和编译,而不接触实际代码吗?如果是,是哪个?

Thanks.

谢谢。

EDIT: no previous declarations or mentions to made_up_function_nameare present anywhere else. Meaning that a grep -Rof the whole filesystem will onlyshow that exact single line of code.

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

回答by Dmitry Yudakov

Yes, it is possible to avoid reporting undefined references - using --unresolved-symbolslinker option.

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

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

From man ld

man ld

--unresolved-symbols=method

Determine how to handle unresolved symbols. There are four possible values for method:

       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.

The behaviour for shared libraries on their own can also be controlled by the --[no-]allow-shlib-undefined option.

Normally the linker will generate an error message for each reported unresolved symbol but the option --warn-unresolved-symbols can change this to a warning.

--unresolved-symbols=方法

确定如何处理未解析的符号。method 有四个可能的值:

       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 可以将其更改为警告。

回答by Heisenbug

If you declare the prototype of the function before using it , it shold compile. Anyway the error while linking will remain.

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

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

回答by Reinstate Monica

TL;DRIt cannot complain, but you don'twant that. Your code will crash if you force the linker to ignore the problem. It'd be counterproductive.

TL; DR可以不抱怨,但你希望出现这种情况。如果您强制链接器忽略该问题,您的代码将会崩溃。会适得其反。

Your code relies on the ancient C (pre-C99) allowing functions to be implicitly declared at their point of use. Your code is semantically equivalentto the following code:

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

void function()
{
    int made_up_function_name(...); // The implicit declaration

    made_up_function_name(); // Call the function
    return;
}

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 implementationfor made_up_function_name()or by removing the nonsensical call. That's all there's to it. No linker-fiddling involved.

链接器正确地抱怨包含编译的目标文件function()引用了一个在其他任何地方都找不到的符号。你必须修复它提供了实现made_up_function_name()或通过删除无意义的呼叫。这就是全部。不涉及链接器摆弄。

回答by Tim Williscroft

And then there is this nastiness with the -D flag passed to GCC.

然后就是传递给 GCC 的 -D 标志的糟糕之处。

$cat undefined.c
void function()
{
    made_up_function_name();
    return;
}


int main(){
}

$gcc undefined.c -Dmade_up_function_name=atexit
$

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.

想象一下,寻找 made_up_function_name 的定义——它在代码中还没有出现在任何地方“做事”。我想不出一个很好的理由在代码中做这件事。

The -D flag is a powerful tool for changing code at compile time.

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

回答by Bo Persson

If function()is never called, it might not be included in the executable, and the function called from it is not searched for either.

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

回答by Sjors Telgen

When you build with the linker flag -ror --relocatableit will also not produce any "undefined reference" link error messages.

当您建立与链接标志-r或者--relocatable它也不会产生任何“未定义的引用”链接错误消息。

This is because -rwill link different objects in a new object file to be linked at a later stage.

这是因为-r将在稍后阶段链接的新对象文件中链接不同的对象。

回答by AnT

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

POSIX 链接器运行所依据的“标准”算法使代码可以编译和链接而不会出现任何错误。详情请看这里:https: //stackoverflow.com/a/11894098/187690

In order to exploit that possibility the object file that contains your function(let's call it f.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 to functionor any other function present in f.o. Under such circumstances linker will see no reason to retrieve f.ofrom the library. Linker will completely ignore f.o, completely ignore functionand, therefore, remain completely oblivious of the call to made_up_function_name. The code will compile even though made_up_function_nameis not defined anywhere.

为了利用这种可能性,应该将包含您的function(我们称之为f.o)的目标文件放入一个库中。这个库应该在编译器(和/或连接器)的命令行中提到的,而是由那一刻没有其他目标文件(先前在命令行中提到)应该作出任何电话function或任何其他存在的功能f.o。在这种情况下,链接器将没有理由f.o从库中检索。链接器将完全忽略f.o、完全忽略function并因此完全忽略对 的调用made_up_function_name。即使made_up_function_name没有在任何地方定义,代码也会编译。