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