Case 1: multiple definitions of a function
module1.cpp:
void f(){}
main.cpp:
void f(){} // error LNK2005: "void __cdecl f(void)" (?func@@YAXXZ) already defined in module1.obj
int main(){}
Case 2: multiple definitions of a class
module1.cpp:
class C{};
main.cpp:
class C{}; // OK
int main(){}
In the Case 1, as expected, (Microsoft) linker comes across two definitions of the same function and issues an error. In Case 2, it allows two definitions of the same class.
Question 1: Why linker doesn't complain when having multiple definitions of the same class? Is it related to the fact that function name is just the name of the address where its instructions start and class name is the name of a new type?
Furthermore, linker won't complain even if we use different definitions of the class (I added functions that call class constructors so they appear in the symbol table):
module1.cpp:
class MyClass
{
int n;
public:
MyClass() : n(123){}
};
void func()
{
MyClass c;
}
main.cpp:
class MyClass
{
float n;
public:
MyClass() : n(3.14f){}
};
int main()
{
MyClass c;
}
I set the compiler option so it generates COD
file along OBJ
files. I can see that both constructors appear under the same mangled name (??0MyClass@@QAE@XZ
), each in its own unit (COD
file). It is expected that if some symbol is referenced in a module, linker will use its definition from the same module, if it exist. If not, it will be using symbol definition from the module where it is defined. And this can be dangerous as it seems that linker picks symbol from the first object file it comes across:
module1.h:
#ifndef MODULE1_H_
#define MODULE1_H_
void func1();
#endif
module1.cpp:
#include <iostream>
#include "module1.h"
class MyClass
{
int myValue;
public:
MyClass() : myValue(123)
{
std::cout << "MyClass::MyClass() [module1]" << std::endl;
}
void foo()
{
std::cout << "MyClass::foo() [module1]: n = " << myValue << std::endl;
}
};
void func1()
{
MyClass c;
c.foo();
}
module2.cpp:
#include <iostream>
class MyClass
{
public:
MyClass()
{
std::cout << "MyClass::MyClass() [module2]" << std::endl;
}
};
// it is necessary that module contains at least one function that creates MyClass object
void test2()
{
MyClass c;
}
main.cpp:
#include "module1.h"
int main()
{
func1();
}
If object files are listed in this order when passing to the linker:
module2.obj module1.obj main.obj
linker will pick constructor MyClass::MyClass
from the first obj file but MyClass::foo
from the second one so the output is unexpected (wrong):
MyClass::MyClass() [module2]
MyClass::foo() [module1]: n = 1
If object files are listed in this order when passing to the linker:
module1.obj module2.obj main.obj
linker will pick both MyClass
members from the first obj file:
MyClass::MyClass() [module1]
MyClass::foo() [module1]: n = 123
Question 2: Why are linkers designed in the way that they allow multiple class definitions which can lead to errors described above? Isn't it wrong that linking process depends on the order of object files?
It seems that linker picks the first symbol definition it comes across when scanning object files and then silently discards all subsequent definition duplicates.
Question 3: Is this how linker builds its symbol lookup table?
boost::thread
as a member and move operation would always fail with access violation...but when I excluded from the project cpp file with the another definition of the class with the same name, the problem was solved...). This is why I started digging into this. – Bojan Komazec