Patrick
Patrick

Reputation: 141

How to apply ODR(One Definition Rule) in c++?

I read the page Definitions and ODR and I also read several relevant questions about ODR. Still don't understand why it is important.

For example, in file1.cpp:

int val = 1;

In file2.cpp:

int val = 2;

In main.cpp:

extern int val;

This case violates the ODR. But in real cases, will anyone do this? I mean one definition for a variable with the same name of the same type seems to be something natural. Even if someone did this, compiler or linker won't agree. I don't understand why we should care about ODR because if we write the wrong code, compiler or linker will give the error. Is it possible to violate ODR without being detected? Can anyone list some real cases or mistakes we often make?

Upvotes: 0

Views: 333

Answers (2)

user743382
user743382

Reputation:

I don't understand why should we care about ODR because if we write the wrong code, compiler will give error.

The ODR is the only thing allowing compilers to issue an error message. If we didn't have the ODR, compilers would be required to accept such code.

Is it possible to violate ODR while the code can be compiled?

Sure. Depending on the compiler, this may compile and link without any problems, or it may fail:

extern int var;
int main() {
  int myvar = var;
}

Note the lack of a definition of var here.

Some compilers see that the local variable myvar is completely unused, and therefore remove the reference to var as well. Other compilers/linkers will complain about the missing definition of var. And for yet some others, it depends on which compiler flags you pass.

Another example:

// t1.cc
int var;
// t2.cc
long var;

Some compilers give int var and long var the same internal name and detect the conflict, other compilers include the type and don't see any conflict.

Upvotes: 3

ovanes
ovanes

Reputation: 5673

Small note on fixing the case

You can declare such variable as static in the translation unit, or within an anonymous namespace.

static global variables do have internal linkage and thus do not violate ODR.

file1.cpp

 static int val = 1;
 // OR
 namespace
 {
   int val = 1;
 }

file2.cpp

static int val = 2;
// OR
namespace
{
  int val = 2;
}

Potential Case from Real Life

What if you have 2 DLLs, or SOs both featuring the same global variable and you load both shared libs in your application?

Upvotes: 2

Related Questions