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

发布于 2024-10-30 04:19:34 字数 481 浏览 1 评论 0原文

在什么情况下,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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

追我者格杀勿论 2024-11-06 04:19:34

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

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

来自man ld

--unresolved-symbols=方法

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

 忽略全部
           不要报告任何未解析的符号。

       全部报告
           报告所有未解析的符号。这是默认设置。

       忽略对象文件
           报告共享中包含的未解析的符号
           库,但如果它们来自常规对象则忽略它们
           文件。

       忽略共享库中的内容
           报告来自常规对象的未解析符号
           文件,但如果它们来自共享库则忽略它们。这
           众所周知,在创建动态二进制文件时可能很有用
           它应该引用的所有共享库
           包含在链接器的命令行中。

共享库本身的行为也可以是
由 --[no-]allow-shlib-undefined 选项控制。

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

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

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

From 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.

辞慾 2024-11-06 04:19:34

如果在使用函数之前声明函数的原型,则它应该编译。无论如何,链接时的错误仍然存​​在。

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

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;
}
为人所爱 2024-11-06 04:19:34

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()的实现或删除无意义的调用来修复它。这就是全部内容了。不涉及链接器摆弄。

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:

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

只有影子陪我不离不弃 2024-11-06 04:19:34

当您使用链接器标志 -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.

倾其所爱 2024-11-06 04:19:34

然后,-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 标志是在编译时更改代码的强大工具。

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

$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.

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

小帐篷 2024-11-06 04:19:34

如果 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.

梦里的微风 2024-11-06 04:19:34

POSIX 链接器操作所依据的“标准”算法使得代码编译和链接没有任何错误的可能性成为可能。有关详细信息,请参阅此处: https://stackoverflow.com/a/11894098/187690

为了利用该对象的可能性包含您的函数(我们称之为fo)的文件应放入库中。该库应该在编译器(和/或链接器)的命令行中提及,但此时没有其他目标文件(在命令行中前面提到过)应该对 functionfo 中存在的任何其他函数。在这种情况下,链接器将认为没有理由从库中检索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 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 function or any other function present in f.o. Under such circumstances linker will see no reason to retrieve f.o from the library. Linker will completely ignore f.o, completely ignore function and, therefore, remain completely oblivious of the call to made_up_function_name. The code will compile even though made_up_function_name is not defined anywhere.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文