开发者

unpredictable behavior of Inline functions with different definitions

开发者 https://www.devze.com 2022-12-16 05:54 出处:网络
I have the following source files: //test1.cpp #include <iostream> using namespace std; inline void foo()

I have the following source files:

//test1.cpp
#include <iostream>
using namespace std;

inline void foo()
{
  cout << "test1's foo" << endl;
}

void bar();

int main(int argc, 开发者_开发百科char *argv[])
{
  foo();
  bar();
}

and

//test2.cpp
#include <iostream>

using namespace std;

inline void foo()
{
    cout << "test2's foo" << endl;
}

void bar()
{
    foo();
}

The output:

test1's foo
test1's foo

Huh??? Ok, so I should have declared the foos static... but shouldn't this kind of thing generate a linker error, or at least a warning? And how does the compiler "see" the inline functions from across compilation units?

EDIT: This is using gcc 4.4.1.


You are running into the one-definition-rule. You are not seeing any error because:

[Some] violations, particularly those that span translation units, are not required to be diagnosed

What going on under the covers is that the compiler is not inlining those functions (many compilers will not inline a function unless the code is compiled with the optimizer). Since the function is inline and can appear in multiple translation units, the compiler will mark the function as link-once which tells the linker that it not treat multiple definitions as an error but just use one of them.

If you really want them to be different, you want a static function.


R Samuel Klatchko's answer is correct, but I'll answer part that he didn't.

"And how does the compiler "see" the inline functions from across compilation units?"

It doesn't. It sees the external definitions of functions that are declared not to be static. For such functions, the compiler can inline if it wishes but it also has to generate code callable from outside.


The inline function is placed in a COMDAT section. That's a signal to the linker that it is free to pick any one of the multiple definitions it encounters. You'll get another output message when you reverse the link order.

Another way to place definitions in a COMDAT section (compiler allowing) is:

__declspec(selectany) int globalVariableInHeader = 42;

Which is handy to avoid the "extern" song and dance. Clearly, this mechanism was designed to allow multiple definitions introduced by one header file getting #included by multiple source files to be resolved by the linker. Fwiw, MSVC has the exact same behavior.

0

精彩评论

暂无评论...
验证码 换一张
取 消