As I have understood, a class can be defined in multiple translation units aslong they’re identical. With that in mind, consider the following examples:
//1.cpp
class Foo{
public:
int i;
};
void FooBar();
void BarFoo(){
Foo f;
}
int main(){
FooBar();
BarFoo();
}
//2.cpp
class Foo{
public:
std::string s;
};
void FooBar(){
Foo f;
}
This compiles and I don’t get a crash.
If I do the following changes:
//1.cpp
Foo FooBar();
//2.cpp
Foo FooBar(){
Foo f;
return f;
}
I get a crash. Why does one result in a crash and the other doesn’t. Also, am I not violating ODR in the first example? If I am, why does it compile ok?
The program is ill-formed for the reason you stated. The compiler is not required a diagnostics, but I don’t see a point in discussing reasons for a crash in an ill-formed program.
Still, let’s do it:
The first example probably doesn’t crash because
FooBar‘s behavior doesn’t affect the run ofmain. The method is called, it does something, and that’s it.In the second example, you attempt to return a
Foo.FooBarreturns the version ofFoodefined in2.cpp.mainappears in1.cppso it expects the version ofFoodefined in1.cpp, which is a completely different version – different members, sizes. You most likely get a corruption on the destructor. (just a guess)EDIT: this does break the one definition rule:
3.2 One definition rule [basic.def.odr]