Search code examples
c++c++11linkerinlineunspecified-behavior

unspecified ouput using inline function in c++


I was playing with code to understand internal and external linkage in c++.I came up with the code whose out seems to vary depending on the sequence in which it is linked.


test1.cpp

#include<iostream>
using namespace std;
inline int c()
{
     static int p=0;
     p++;
     return p;
}
void a()
{
     cout<<"\nIn function a() , c = "<<c();
}


test2.cpp

#include<iostream>
using namespace std;

inline int c()
{
    static int p=12;
    p++;
    return p;
}

void b()
{
       cout<<"\nIn function b() , c = "<<c();
} 


driver.cpp

#include<iostream>
using namespace std;

void a();
void b();
int c();

int main()
{
   b();
   a();
   a();
   b();
   cout<<"\nIn function main() = , c "<< c();
   cout<<"\n";
}

output 1 :-

when compiles as follows :- 

bash#>g++ -c test1.cpp
bash#>g++ -c test2.cpp
bash#>g++ -c driver.cpp

bash#>g++ -o out driver.o test1.o test2.o
bash#>./out

In function b() , c = 1
In function a() ,  c = 2
In function a() ,  c = 3
In function b() , c = 4
IN main() , c = 5

In above output , compiler is considering c() defined in test1.cpp

output 2:- changing sequence of test1.o and test2.o while linking.

bash#>g++ -o out driver.o test2.o test1.o

In function b() , c = 13
In function a() ,  c = 14
In function a() ,  c = 15 
In function b() , c = 16
IN main() , c = 17

In above output , compiler is considering c() defined in test2.cpp

I was perplexed when i made minor changes in the code , which are as follows :-
1) if I do not call c() in function a() [test1.cpp] and c() in funciton b()[test2.cpp]

//test1.cpp changes
void a()
{
   cout<<"\nIn function a() , c = "; // not calling c()
}

//test2.cpp changes
void b()
{
    cout<<"\nIn function b() , c = "; // not calling c()
} 

I get following error while linking :-

bash#>g++ -o out driver.o test1.o test2.o
driver.o: In function `main':
driver.cpp:(.text+0x1f): undefined reference to `c()'
collect2: ld returned 1 exit status

2) If i call c() in any one of the file i.e either in test1.cpp or in test2.cpp , then i wont get linker error.

Could anyone please help me in understanding this behaviour.

Thanks in advance.


Solution

  • Your program has undefined behavior because it violates the One Definition Rule. Two different translation units are defining a function with same name and signature, but with different bodies.

    Per paragraph 3.2/6 of the C++11 Standard:

    [...] Given such an entity named D defined in more than one translation unit, then

    — each definition of D shall consist of the same sequence of tokens; and

    [...]

    Your program is also ill-formed because function c() is declared as inline in test1.cpp and test2.cpp, but not in driver.cpp. Per paragraph 7.1.2/4

    [...] If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. [...]

    The "no diagnostic is required" bit means that the compiler (or linker) may or may not report an error for a violation of this rule. That means you have to be very careful to break it.