multiple definition of inline function
Solution 1
This answer is divided into the following sections:
- How to reproduce the
duplicate definition of inline function - func3
problem and why. - Why defintion of
func3
is a duplicate instead offunc1
. - Why it compiles using
g++
How to produce the duplicate definition of inline function - func3 problem
The problem can be successfully reproduced by
- Rename
tran.cpp
totran.c
- Compile with
gcc -o main main.c tran.c
@K71993 is actually compiling using the old gnu89 inline semantics, which is different from C99. The reason for renaming tran.cpp
to tran.c
is to tell the gcc driver to treat it as C
source instead of C++
source.
Why definition of func3 is a duplicate instead of func1.
GNU 89 inline semantics
The following text is quoted from GCC Document: An Inline Function is As Fast As a Macro explains why func3
is a duplicate definition instead of func1
, since func3
(instead of func1
) is an externally visible symbol (in GNU89 inline semantics)
When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.
If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.
C99 inline semantics
If compiled with C99 standard, i.e., gcc -o main main.c tran.c -std=c99
, the linker will complain that definition of func1
is a duplicate due to the reason that extern inline in C99 is a external definition as mentioned in other posts and comments.
Please also refer to this execellent answer about semantic differents between GNU89 inline
and C99 inline.
Why it compiles using g++
.
When compiled with g++
, the source program are considered as C++
source. Since func1
, func2
and func3
are defined in multiple translation units and their definitions are different, the One Defintion Rule of C++ is violated. Since the compiler is not required to generate dignostic message when definitions spans multiple translation units, the behavior is undefined.
Solution 2
The compiling error is because there is a duplicate definition of func1();
Because func1() is defined using extern inline, it will produce a external definition.
However, there is also an external definition in tran.c, which cause multiple definition error.
However, func2() and func3() do not produce an external definition, hence no redefinition error.
You might want to look at here http://www.greenend.org.uk/rjk/2003/03/inline.html.
Also, take a note that c++ and c treats inline functions differently, and even in c, different standards (c89 vs. c99) treats inline functions differently.
Solution 3
Maybe you should post the actual code. The snippets you show don't compile:
- inline.h has
extern inline int func1(void)
That doesn't make any sense. - main.h has
#define <stdio.h>
I think you meantinclude
instead.
Once I fixed those and compiled with gcc, it compiled fine and I got the following output
5
6
7
When I compile with g++, I get this output:
5
6
700
That happens because func3() is not static in inline.h
Solution 4
Your code is invalid from the C++ point of view, since it blatantly violates the One Definition Rule. The only reason you managed to compile it by C++ compiler is the loose error checking in your C++ compiler (it happens to be one of those parts of ODR where "no diagnostic is required").
Your code is not valid C, because it provides duplicate external definition of function func1
. Note that it is func1
, not func3
that is problematic from the C point of view. There's nothing formally wrong with your func3
. Your func2
is also OK, as long as the two definitions never "meet" each other in the same translation unit.
One possible reason you might be getting a different diagnostic report from your compiler is that your C compiler might be supporting inline
functions in some non-standard compiler-specific way (either a pre-C99 compiler or a modern compiler run in non-standard "legacy" mode).
Frankly, I find it hard to believe you are getting an error report about func3
from any compiler, assuming the code you posted accurately represents what you are trying to compile. Most likely what you posted is not the real code.
Related videos on Youtube
K71993
Updated on April 23, 2022Comments
-
K71993 about 2 years
I have gone through some posts related to this topic but was not able to sort out my doubt completely. This might be a very naive question.
I have a header file
inline.h
and two translation unitsmain.cpp
andtran.cpp
.Details of code are as below
inline.h
#ifndef __HEADER__ #include <stdio.h> extern inline int func1(void) { return 5; } static inline int func2(void) { return 6; } inline int func3(void) { return 7; } #endif
main.c
#define <stdio.h> #include <inline.h> int main(int argc, char *argv[]) { printf("%d\n",func1()); printf("%d\n",func2()); printf("%d\n",func3()); return 0; }
tran.cpp
//(note that the functions are not inline here) #include <stdio.h> int func1(void) { return 500; } int func2(void) { return 600; } int func3(void) { return 700; }
The above code compiles in g++, but does not compile in gcc (even if you make changes related to gcc like changing the code to .c, not using any C++ header files, etc.). The error displayed is "duplicate definition of inline function - func3".
Can you clarify why this difference is present across compilers?
Also, when you run the program (g++ compiled) by creating two separate compilation units (
main.o
andtran.o
) and create an executablea.out
, the output obtained is:500
6
700Why does the compiler pick up the definition of the function which is not inline. Actually, since
#include
is used to "add" the inline definition I had expected5,6,7
as the output. My understanding was during compilation since the inline definition is found, the function call would be "replaced" by inline function definition.Can you please tell me in detailed steps the process of compilation and linking which would lead us to
500,6,700
output. I can only understand the output 6.-
MKroehnert about 14 yearsAren't you missing a "#define HEADER" after "#ifndef HEADER" ??
-
AnT stands with Russia over 11 yearsWhat command line switches are you passing to GCC? The specification of
inline
in C99 is different from the legacy GCC-specific extension. Which specification are you trying to use? -
wildplasser over 11 years1)
#ifndef __HEADER__
(preprocessor) identifiers beginning with one or more underscores are reserved for the language ore implementation. 2) which language, C or C++? -
smbear over 11 yearsYour example is missing
#define __HEADER__
. Also, here is a link (in my opinion it might be helpful): greenend.org.uk/rjk/tech/inline.html
-
-
nategoose about 14 years
extern inline
is used by some compilers to say "inline this if you see a use and can inline, but if you see a use where it cannot be inlined assume that another compilation unit will provide a non-inline version of this function". Inability to inline could be because the function's address was assigned to a variable or passed to another function. I believe that gcc header files useextern inline
quite often. -
AnT stands with Russia over 11 years@nategoose:
extern inline
is a standard feature of C99 language. It is not about "some compilers". All C99-conformant compilers must recognizeextern inline
definition as an external definition for the function. -
nategoose over 11 years@AndreyT: Some compilers are C99. :-) Some that aren't (or aren't in C99 mode) still accept
extern inline
-
Lazureus over 10 yearsAs far as I know pure C89 doesn't support inline keyword, there are only some extensions which supports inline, but in this case you're not writing anymore in the pure C89 but in the some dialect of C89.