删除内联函数调用会导致无法解决的外部符号错误

Removing inline function call results in unresolved external symbol error

提问人:Luchian Grigore 提问时间:8/5/2014 更新时间:8/5/2014 访问量:851

问:

我试图证明您需要在所有使用它的 TU 中为函数定义。但是,以下代码编译良好 (MSVS 2010):inline

公司

inline void foo();

测试.cpp

#include "inc.h"

void x();
int main()
{
    foo();  // <--- compilation fails if I remove this call
    x();
    return 0;
}

void foo()
{
}

测试2.cpp

#include "inc.h"

void x()
{
    foo();
}

请注意,函数调用是为了防止优化。这编译,虽然在 中声明并仅在 中定义,但也在 中使用。fooinlinetest.cpptest2.cpp

如果我注释掉对 in 的调用,我会得到预期的错误。foomain()

函数“void __cdecl foo(void)” (?foo@@YAXXZ) 引用 __cdecl x(void)“ (?x@@YAXXZ) 致命错误 LNK1120:1 个未解决的外部问题

为什么在那里打电话很重要?代码在任何一种情况下都不应该起作用,对吧?foo

添加到 的声明 in 也会使其编译(无论对 in 的调用如何)。externfooinc.hfoomain

C++ 可视化工作室 内联

评论

0赞 Dalibor Frivaldsky 8/5/2014
也许你对“内联”关键词的看法是错误的。“inline” 应该告诉链接器,如果它在多个 TU 中找到 “foo()” 的定义,它是可以的,并且链接不应该因多定义错误而失败。我不认为它告诉链接器“foo()”的定义应该在每个 TU 中。我的猜测是链接器可以自由使用它在任何处理的 TU 中找到的“foo()”的任何定义。调用时,test.obj包含“foo()”的定义,因此在处理test2.obj时链接器可以使用它。当你不在 main() 中调用它时,不存在“foo()”的定义
0赞 Luchian Grigore 8/5/2014
@DaliborFrivaldsky令我惊讶的是,它不会因“未定义符号”而不是“多个定义符号”而失败。7.1.2/4 告诉我这应该发生 -An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case
0赞 Dalibor Frivaldsky 8/5/2014
但是 “foo()” 不是在 test2.cpp 中使用的 ODR,因为在编译 test2.cpp 时没有提供 “foo()” 的定义。这意味着“foo()”不必在test2.obj中定义。你对标准的引用并没有说链接器因此被禁止使用其他 TU 中发现的任何其他定义的“foo()”定义
0赞 Luchian Grigore 8/5/2014
@DaliborFrivaldsky那么为什么在删除对 的调用时会失败呢?foo
0赞 Dalibor Frivaldsky 8/5/2014
因为它没有在任何 TU 中定义。作为一个内联函数,编译器仅在使用时生成其定义

答:

2赞 Mark B 8/5/2014 #1

这在 3.2/3 中非常清楚:

...An inline function shall be defined in every translation unit in which it is used.

如果你没有在每个这样的 TU 中定义它,那么所有的赌注都是失败的,编译器所做的任何事情都很好,包括在某些情况下似乎可以工作,而在其他情况下却无法工作。