Link to home
Start Free TrialLog in
Avatar of AssafLavie
AssafLavie

asked on

C++ Linkage

Hi.
I was wondering whether a header file that contains function definitions, that's #included into a number of cpp files gets compiled into each object.
I wrote a function that was implemented in a header file. This header file was used/included by other source files. That made me wonder if VC++ is able to compile the header just once and 'use' it in other objects, or is it just compiled into every object - resulting in bigger code?
Avatar of WilliamGordon
WilliamGordon

Hi AssafLavie,

As far as I've seen, using VC4,5,6 the Microsoft boys/girls seem to recognise the fact that the method implementation has been declared and do not implement the code for each header file hit.  Are you including the function definitions inside a class definition, or including it outside of any class scope?

However this is assuming that you are not talking about templates, for which they do generate code (and how!), but this is really to be expected, when you understand how templates/Microsoft VC works.  Will change in the future though apparently.

What do you mean by "objects"?  C++ objects?  or object code files?

Any function that apears inside a class definition is automaticallly "recommended" for inlining and thus will probably be placed in the code at every place that it is called.  Thus this can cause the function to be duplicate many times.  A function that is defined outside of the class, but in the class definition is not automatically inlined.  How the compile handles the compiled definition of this code is implimentation defined.  However if the function is not inlined, then the compiler and linker are required to produce no more than one copy of the function in the final executable (or DLL etc.)  Typically this is done by by compiling a copy of the function into each object file (OBJ) the includes the function's definition.  Then at link time the linker uses the first of these defintions that it encounters and discards any duplicate definitions.  This is called "dead code stripping".

Does that help at all?
Avatar of AssafLavie

ASKER

Hmm. "Dead code stripping", I guess that's the answer I was looking for.
I was under the impression that once compiled, an object file is linked as-is. I never thought the linker was able to strip away unwanted parts.
The function I was talking about was defined outside the scope of a class. Does that change things?
And what about templates? Are they an exception in any way?
The reason I started thinking about this is because I was compiling this project that had a function, defined in a header file. I got an error about "symbols already defined".. I fixed it by declaring the function as "inline", but than I switched to using an anonymous namespace because i thought this way, the code isn't replicated. (Is it?)

(BTW, thanks WilliamGordon, but your answer was not as complete. Sorry)

>> I never thought the linker was able to
>> strip away unwanted parts.
Very much.  the hypotheticla linkers you see discussed in text books and done as school projects just concatinate together the object files and fix-up  offsets.  A typical real linker does much more, like striping code, and performing some types of optimizations.  removing or adding debug info etc.   A C++ linker does even more.  In C++ the linker may have to invoke the compiler to comple templates for certain data types...   Probalby other things too.
>> The function I was talking about was
>> defined outside the scope of a class.
>> Does that change things?
I don't know because I don't understand completely what your situation is.  i.e. I'm not really sure what  you are asking about.  But a non-inline function may appear only one time in the final product (usually a program, but might be a DLL etc.)  That is required by the standard so that you can safely compare pointers to functions.  (You can also safely compare pointers to inline functions too.  If you generate a pointer to an inline funciton the compiler/linker will insure that the function appears non-inline eactly 1 time in the final product.  And the pointer to that 1 occurance wi.l be used)  So there is never a case where a function appears twice in the final produce (unless it is inlined).  

>> And what about templates? Are they an
>> exception in any way?
As long as you consider expansions of the template for different types to be different functions, they there is no exception.  I.e. if you using Max<int>() from 3 translation units (source code files), you are insured that the final program will contain only 1 non-inline copy of Max<int>().  However it may also contain 1 non inline copy of Max<double>()
>> The reason I started thinking about
>> this is because I was compiling this
>> project that had a
>> function, defined in a header file.
Aha.  Now I understand.  That is a little different than what T told you.

When a program is ccompiled the C++ compiler is submitted a translation unit.   This the source code file (usually .cpp or .cp or .c) file with all the include files included (and portions that aren't included due to conditional compilation removed.  In esssence the translation units is the output of the C pre-processor.  (However many compilers dues the work of the C pre-processor themselves, as part of the compilation.)  

The C++ comples the translation units to object files (usually .obj or .o)  
The linker links the object files into the final produce, pusually a program, maybe a DLL etc.

Now one of the fundamental rules of C/C++ is the one definition rule.  This says that you may define any number of declarations for something (a typedef, a function, a class, a variable etc) but you may define eactly one definition for the something (exactly meaning not more or less).  What this means is that for "something" a definition for it may appear in any number of translation units, it can even appear twice in some transaltion units.  but one and only one translation unit must have the definition fo that something.  When it comes to link time the linker is responsible for enforcing the rule.  if it finds that two or more object files have a definition for something, it is an error.  When no object files have a definition for something, that is also an error.  So this sort of error is only detected at link time, never at compile time.

With this sort of error, don't be fooled by include files.  if you place a a definition in a include file you might say the definition appears 1 time.  but if you include that include file into two translation units, then the definition appears twice!

continues
Now this must seem to contradic what I said earlier.  Well it does an it doesn't.  The one definition rule was absolute for C.  but it was relaxed in C++,--it had to be or clases and templates would be a nightmare.  (both for the programmer writting them and for the implimenter writting the compiler.   You can include a function definition inside a class's declaraton like

class X
{
   DoSomething() { cout << something; };
};

Now that is a declaration for X and a definition for DoSomething().  Since DoSomething() is defined, you rule would say that the class definition can then only appear in one transalation unit, or there woudl be multiple definitions of DoSomething().  that woudl be too limiting.  the result would be that programers would not use definitions in the class--which is very desirable.   so it was decided that inclass definitions could appear in multiple translation units and that it was the responsiblity of the implimenter to somehow see to it that onley one occurance appears in the final product.

contines
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
:)
That was great man. Thanks alot.