Inline function linkage
Asked Answered
V

4

25

I can't make sense of the following behavior: one header with some basic types, and another header in which I use these types in several functions. Afterward I started constructing classes based on my defined types and functions. In the function header if I leave the following signature:

void whateverFunction(parameters)

The linker points out that there are multiple definitions of whateverFunction. Now if change it to:

inline void whateverFunction(parameters)

the linkage problem is gone and all compiles and links well. What I know concerning inline is that it replaces every function call with it's code other than that it's a pretty dark, so my question is:

How does the linker treats inline functions in C++?

Vasta answered 16/11, 2010 at 11:27 Comment(1)
See "what is/are the purpose(s) of inline?" for the details, especially the part on the One Definition Rule.Decrease
P
37

When the function in the header is not inline, then multiple definitions of this function (e.g. in multiple translation units) is a violation of ODR rules.

Inline functions by default have external linkage. Hence, as a consequence of ODR rules (given below), such multiple definitions (e.g. in multiple translation units) are Okay:

$3.2/5- "There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then

— each definition of D shall consist of the same sequence of tokens; and [...]

How the linker treats inline functions is a pretty much implementation level detail. Suffice it to know that the implementation accepts such mulitple defintions within the limitations of ODR rules

Note that if the function declaration in header is changed to 'static inline....', then the inline function explicitly has internal linkage and each translation unit has it's own copy of the static inline function.

Poland answered 16/11, 2010 at 11:38 Comment(2)
Inline functions by default have external linkage.: I find this statement misleading. Inlined code is not linked at all, at least not under the function name. See Marcelo's answer.Sixtyfourmo
On modern compilers, one can see inline as a keyword to permit multiple definition instead of optimizing hint. The compiler can decide not to inline an inline function, and the linker can choose any one across compilation units. The programmer should make sure that an inline function across compilation units are identical. Otherwise undefined behavior arises.Clytemnestra
H
8

The linker may not see inline functions at all. They are usually compiled straight into the code that calls them (i.e., the code is used in place of a function call).

If the compiler chooses not to inline the function (since it is merely a hint), I'm not sure, but I think the compiler emits it as a normal non-inline function and somehow annotates it so the linker just picks the first copy it sees and ignores the others.

Heribertoheringer answered 16/11, 2010 at 11:31 Comment(0)
C
0

It seems indeed counter-intuitive that an inline function has "external linkage" in C++ lingo; after all, the function symbol (its name) is not exported at all in the resulting object file — indeed, there often will not be any function but just inlined code! —, and therefore cannot be linked against, as opposed to the result of external linkage for normal variables and functions.

There is an IBM article which discusses the consequences of inline functions having external linkage, and it agrees with the cppreference page. In short,

  • The function has the same address in different translation units (this may matter if you compare function pointers);
  • type declarations within the inline function are the same in all translation units (this may be logically tied to the next point, see footnote);
  • function-local static variables are shared between the functions (this is extremely important for initialization and resource allocation strategies).

I can imagine that the latter point is the main motivation for the external linkage of inline functions. Initialization of function-local static variables is protected against concurrency and performed only once. It is a common and fail-proof pattern for thread-safe resource allocation. The variables must be shared for that.1 It would be sad to give that up; in particular, one-line functions which return a resource which are prime candidates for inlining. If they could not guarantee that the resource is initialized one would have to choose between the two:

inline FILE *logfile()
{
   static FILE *fp = openLogfile(); // done once, thread-safe
   return fp; // all subsequent calls simply return fp.
}

External linkage guarantees that all calls of this inline function, across translation units, will return the same file pointer.


1 The "same type" provision may be related to that; imagine that an inline function defines a static custom sentinel class object with a resource handle that is responsible for freeing a resource.

Chargeable answered 26/1 at 14:6 Comment(0)
S
-2

The inline just masks the problem. Having multiple definition points out a problem somewhere.

Juste be careful about how you use your headers. Dont forget to : - << #ifndef HEADER_NAME / #define HEADER_NAME / #endif >> to avoid multiple inclusion. - Do not use indirect inclusion : if you use a type in a file, add the corresponding header, even if another header in the same file includes it.

Surinam answered 16/11, 2010 at 13:6 Comment(2)
You can include the same header from two different translation unit and the guard doesn't help you.Latreshia
Damn my answer was indeed bad but I did not expect negative votes so along after ^^Surinam

© 2022 - 2024 — McMap. All rights reserved.