Question

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.

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top