ODR@functions(+classes)

OneDefinitionRule is more strict on global variables (which have static duration). You can’t have 2 global variables sharing the same name. Devil is in the details:

As explained in various posts, you declare the same global variable in a header file that’s included in various compilation units, but you allocate storage in exactly one compilation unit. Under a temporary suspension of disbelief, let’s say there are 2 allocated storage for the same global var, how would you update this variable?

With free function f1(), ODR is more relaxed. http://www.drdobbs.com/cpp/blundering-into-the-one-definition-rule/240166489 explains the Lessor ODR vs Greater ODR. Lessor ODR is simpler and more familiar, forbidding multiple (same or different) definitions of f1() within one compilation unit.

My focus today is the Greater ODR therein. Obeying Lessor ODR, the same inline function is often included via a header file and compiled into multiple binary files. If you want to put non-template function definition in a shared header file but avoid Great ODR, then I think it must be inline, implicitly or explicitly. I find the Dr Dobbs article unclear on this. In my test, when a function was defined in a shared header without “inline” keyword, then compiler failed with ODR.

The most common practice is to move (inline or otherwise) function definitions out of shared headers, so the linker (or compiler) sees only one definition globally.

With inline, Linker actually sees multiple (hopefully identical) physical copies of func1(). Two copies of this function are usually identical definitions. If they actually have different definitions, compiler/linker can’t easily notice and are not required to verify, so no build error (!) but you could hit strange run time errors.

Java linker is simpler and never cause any problem so I never look into it.

//* if I have exactly one inline, then the non-inlined version is used. Linker doesn't detect the discrepancy between two implementations.
//* if I have both inline, then main.cpp won't compile since both definitions are invisible to main.cpp
//* if I remove both inline, then we hit ODR 
//* objdump on the object file would show the function name IFF it is exposed i.e. non-inline
::::::::::::::
lib1.cpp
::::::::::::::
#include <iostream>
using namespace std;

//inline
void sameFunc(){
    cout<<"hi"<<endl;
}
::::::::::::::
lib2.cpp
::::::::::::::
#include <iostream>
using namespace std;

inline
void sameFunc(){
    cout<<"hey"<<endl;
}
::::::::::::::
main.cpp
::::::::::::::
void sameFunc(); //needed
int main(){
  sameFunc();
}
Advertisements

One thought on “ODR@functions(+classes)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s