Inline function multiple definition - c

I have the following three files:
inline_header.h
#ifndef INLINE_HEADER_H
#define INLINE_HEADER_H
inline int func1() {
return 1;
}
#endif
source1.c
#include "inline_header.h"
source2.c
#include "inline_header.h"
int main() {
func1();
}
When I compile just source2.c with gcc source2.c it compiles. However, when I attempt to compile with gcc source1.c source2.c I get the a multiple definition error as follows:
/tmp/cchsOaHF.o: In function `func1':
source2.c:(.text+0x0): multiple definition of `func1'
/tmp/ccEyUW0T.o:source1.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
I am compiling with gcc 4.8.4 on Ubuntu 14.04.
I've tried looking this up and found a similar question multiple definition of inline function. However in his case, the error is caused by a redefinition of his inline function. In my case, I am not redefining it (or at least not explicitly...).

When you compile source1.c into source1.o, it contains a definition of func1. Similarly, when you compile source2.c into source2.o, it also contains a definition of func1. So when you link source1.o and source2.o, you get a multiple definition error.
The reason the include guards don't prevent this is because source1.c and source2.c are each compiled separately. Include guards only help within a single compilation unit.
If this were not an inline function, you'd put a declaration in the header file:
int func1();
Then put the definition in exactly one source file.
However, you're defining the function as inline. So you need to also declare it as static so that each compilation unit gets its own copy of the function.
EDIT:
The multiple definition error is happening because you're compiling in C89 mode by default, and inline isn't part of that version of the standard. As such, it seems that gcc is basically ignoring that keyword.
If you compile in C99 or C11 mode using -std=c99 or =std=c11 with this code, you'll actually get an "undefined reference" error. Section 6.7.4p7 of the C standard states the following:
Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. An inline definition does not provide an external definition for the function,and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition
What this means is that a function with only inline doesn't actually provide a definition of a function that can be called. In your case, you want to add the static storage class specifier to force a local definition in each file.
Interestingly, if you compile this code as is with -O1 and -std=c99, gcc will physically inline the function and it will compile and run cleanly.

If you wish to place this sort of function in a header, it must also be static:
static inline int func1() {
return 1;
}
This will cause the symbol to be local to each compilation unit (file), avoiding any linker errors.
Also, from the gcc manual:
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.

Related

Using a regular function with the name of an inline function in C

Assume I have two files:
1.c
inline int test(int in){
return in+1;
}
int get();
int main(){
return get();
}
2.c
int test(int in){
return in+9;
}
int get(){
return test(5);
}
Compiling it with gcc 1.c 2.c goes smoothly with no errors.
Is this defined behaviour? i.e test in 1.c is different from the other function and we essentially have 2 test functions in generated in code?
The inline copy of test in 1.c doesn't actually constitute a external function definition, allowing for test in 2.c to be used by the program. If you were to call get in the main function and print the result, you would get the value 14.
If you were to call test from the main function, is could use either version of the function. Which one it does use is unspecified.
The mechanics of inline are specified in section 6.7.4 of the C standard, paragraphs 6 and 7:
6 A function declared with an inline function specifier is an inline function. Making af unction an inline function
suggests that calls to the function be as fast as
possible.138) The extent to which such suggestions are
effective is implementation-defined.139)
7 Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions
apply: If a function is declared with an inline function
specifier, then it shall also be defined in the same
translation unit. If all of the file scope declarations for a
function in a translation unit include the inline function
specifier without extern, then the definition in that
translation unit is an inline definition. An inline definition
does not provide an external definition for the function, and
does not forbid an external definition in another translation unit.
An inline definition provides an alternative to an external
definition, which a translator may use to implement any call to the
function in the same translation unit. It is unspecified whether a
call to the function uses the inline definition or the external
definition.140)
138 ) By using, for example, an alternative to the usual
function call mechanism, such as ‘‘inline substitution’’. Inline substitution is not textual substitution, nor does it
create a new function.Therefore, for example, the expansion of
a macro used within the body of the function uses the
definition it had at the point the function body appears,
and not where the function is called; and identifiers refer
to the declarations in scope where the body occurs.
Likewise, the function has a single address, regardless of the
number of inline definitions that occur in addition to the
external definition.
139 ) For example, an implementation might never perform inline
substitution, or might only perform inline substitutions to calls in
the scope of an inline declaration.
140 ) Since an inline definition is distinct from the
corresponding external definition and from any other
corresponding inline definitions in other translation units, all
corresponding objects with static storage duration are also distinct
in each of the definitions.
As an example of unspecified behavior, if you added the following line to main:
printf("test(3)=%d\n", test(3));
If you compile in gcc with -O0 you'll get test(3)=12. If you compile with -O1 or higher you'll get test(3)=4.
From this link on inline functions
You can have a separate (not inline) definition in another
translation unit, and the compiler might choose either that or the
inline definition.
So, that's why compiler did not give any error.

Inline function cross compilation issues for ARMv8 architecture using aarch64 linux android clang

I have a questions about using inline keyword in C code (C99).
I know C99 inline semantics are different than C++ or gnuC inline rules,
I have read
http://www.greenend.org.uk/rjk/tech/inline.html
and
extern inline
but, I just can't get this working.
I have a function definition as below in file1.c
inline myfunc(arguments)
{
}
And this function is called from another function in file2.c
In that file2.c I tried using
extern inline myfunc(arguments);
for this function before it is called from the other function
still I keep getting error - implicit declaration of myfunc
or undefined reference error if I remove the extern inline
Due to my code structure, cannot have the myfunc function definition in a header file nor can have it as static inline, as it has to be called from different compilation units.
What is that I am getting wrong? How to fix it.
After lot of reading about this, trial and error I have found answer to my problem above in a way I was looking for - Inline a C function definition present in a C source file, using C99 rules, without putting it in a header file.
I added the attribute always_inline keyword to the function definition and declaration as below and recompiled, it inlines the call to that function.
In file file1.c
__attribute__((always_inline)) void myfunc(arguments)
{
//... function definition
}
and in file1.h which has its declaration , I changed it to be as below
__attribute__((always_inline)) void myfunc(arguments);

Why does inline void foo() { ... } in a common header just work?

Consider the use of inline in C99, with various options (extern'ing, static inline etc), as described here, for example.
I don't understand why the C standard does not allow for just using
void inline foo() { do_stuff(); }
in a common header file, and for that to work everywhere. Why do I have to add static? Isn't what I want clear enough already?
From the gcc site:
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.
What does it mean for you. You cannot define the inline function in the header since it will mean that it will be defined from different translation units (.c files that include it).
Once it is defined static inline then each c file that includes the header will have its own copy of the function.
EDIT
gcc behaves correctly. Inline functions were added to the standard with the introduction of C99. The standard is somewhat ambiguous and states:
Any function with internal linkage can be an inline function. For a
function with external linkage, the following restrictions apply: If a
function is declared with an inline function specifier, then it shall
also be defined in the same translation unit. If all of the file
scope declarations for a function in a translation unit include the
inline function specifier without extern, then the definition in that
translation unit is an inline definition. An inline definition does
not provide an external definition for the function, and does not
forbid an external definition in another translation unit. An inline
definition provides an alternative to an external definition, which a
translator may use to implement any call to the function in the same
translation unit. It is unspecified whether a call to the function
uses the inline definition or the external definition.
What it actually means is that when the compiler sees the inline keyword cannot know if the function was already defined in another translation unit (This will be known only during linking). Now most compilers gcc included will not inline a function without optimizations turned on. So if you try to use an inline function when compiling with -O0 the compiler issues a real call to the function (It assumes it is defined in a another file then the one it is currently compiling). Now when the linker encounters the call it tries to find the function in all compiled objects but fails (because the compiler didn't create a body for the function neither did it inline it - the standard says it doesn't have to create a body for the function and that it can assume there is a definition some where). This is why you get the error: undefined reference to f when you link your project. This is the correct behavior when compiling with -std=c99 onward. It also means that if you want an inline function to have abody you must declare it external only once BUT you must also provide the definition within the same translation unit you declared the function with extrnal linkage.
So in order to get your code to work correctly according to the standard you should do the following:
in the h file just do as you would expect.
inline void f(){ /*DO SOMETHING*/}
And in just one of your code files (.c files) you do:
extern inline void f();
What happens is that now the compiler encounters in just one translation unit both body definition (taken from the header) and a declaration that says it should exist an external definition somewhere and in accordance with the standard creates one for the function.
So the standard says that any function with internal linkage can be declared inline and that the compiler should generate a body for it. In C a function is considered to have internal linkage only when adding the static keyword.
This is why static inline void f() works. Without the static keyword the compiler assumes that the function has external linkage and that is why just specifying inline void f() without also adding extern inline void f() in just one source file will not work.
...C standard does not allow for just using...
That's completely wrong. Your question is based on some incorrect/outdated/compiler specific premise, which has nothing to do with C standard. In C language you don't need static when putting inline function in header file. An inline definition without an explicitly specified extern keyword does not form an external definition for that function. For that reason inline definition without static cannot trigger any multiple-definition-related errors (if that's what you are afraid of).
Moreover, the link that you posted clearly says that C standard does not say anything implied in your question. It says that GCC compiler implements inline differently from what's required by C standard (probably referring to an older version of GCC).
In other words, from C language point of view you can (and should) put
inline void foo() { do_stuff(); }
in the header file. No static required.

Why is static keyword required for inline function?

If I try to compile the following C code without declaring the function static, I get a linker error:
undefined reference to '_fun'
but it works if I don't make it static. In c++, it works just fine without the static keyword.
// Doesn't work
inline int fun()
{
return 3;
}
// Works
static inline int fun()
{
return 3;
}
int main(int argc, const char * argv[])
{
printf("%i", fun());
}
The requirements for inline in C are defined by section 6.7.4 of the ISO C standard. Quoting this section from the N1256
Any function with internal linkage can be an inline function. For a
function with external linkage, the following restrictions apply: If a
function is declared with an inline function specifier, then it
shall also be defined in the same translation unit. If all of the file
scope declarations for a function in a translation unit include the
inline function specifier without extern, then the definition in that
translation unit is an inline definition. An
inline definition does not provide an external definition for the
function, and does not forbid an external definition in another
translation unit. An inline definition provides an alternative to an
external definition, which a translator may use to implement any call
to the function in the same translation unit. It is unspecified
whether a call to the function uses the inline definition or the
external definition.
As far as I can tell, your definition satisfies all those requirements. This:
inline int fun()
{
return 3;
}
is both a declaration and a definition of fun. Without the inline keyword, it would have external linkage.
The tricky part is the last sentence:
It is unspecified whether a call to the function uses the inline
definition or the external definition.
In this case, there is no external definition. You don't say what compiler you're using, but gcc -std=c99 -pedantic apparently chooses, by default, to use the external definition, and since there isn't one, you get a linker error. (Without -std=c99 -pedantic, there's no linker error, but that's because gcc also implements inline as an extension on top of C90.)
If you're only going to be using the function in that one source file, you might as well add the static keyword anyway, to give it internal linkage.
And experiment shows that your program compiles, links, and runs correctly if I compile it with optimization, using any of -O1, -O2, or -O3.
A footnote in the C standard seems to imply that gcc is behaving correctly. An example in the same section has a similar non-static inline function definition:
inline double cels(double t)
{
return (5.0 * (t - 32.0)) / 9.0;
}
followed by:
Because cels has external linkage and is referenced, an external
definition has to appear in another translation unit (see 6.9);
the inline definition and the external definition are distinct and
either may be used for the call.
The Standard's intention seems to be that if an inline function has internal linkage, it should be defined just once in the source file that uses it, but if it has external linkage, the inline definition is an alternative to a non-inline definition that must appear elsewhere. The choice of whether to call the external function or expand the inline definition is left to the whim of the compiler.
Some points not directly relevant to your question:
int fun() should probably be int fun(void). The empty parentheses are legal, but they indicate that the function takes an unspecified number and type(s) of arguments. The void specifies that it takes no arguments, which is what you want.
You need #include <stdio.h> if you're going to call printf; this is not optional.
You don't want const in the declaration of argv. For that matter, since you don't refer to the command-line arguments, you can write int main(void).
C99 inline semantics are subtle - in fact, that whole part of the language (storage duration vs linkage, tentative and inline definitions) is a mess.
While inline acts as a compiler hint in definitions that include a storage class specifier (static or extern) and can basically be ignored, the semantics change if no specifier is present.
A definition like inline int fun(void) { ... } does two things:
First, it declares an identifier with external linkage, without providing a corresponding external definition. This means such a definition must be provided by a different translation unit or we end up with undefined behaviour (probably manifesting as failure to link).
Second, it provides an inline definition, which is an alternative to the external one. As the function body is visible in the current translation unit, the compiler may use it to inline the function or for type specialization.
To get the external definition, until fairly recently, I thought it necessary to repeat the function definition in another translation unit (or fake that with 4 lines of preprocessor code).
However, that's not necessary: A single line of code - a re-declaration of the function that includes the extern specifier - is enough to make the inline definition into an external one.
In your example, this would mean putting
inline int foo(void)
{
return 42;
}
into a header file foo.h and providing a source file foo.c with contents
#include "foo.h"
// force definition to be external instead of inline
// I believe inline could be omitted, but it doesn't hurt
extern inline foo(void);
Why is this useful? As C lacks templates, generic code normally comes with a performance penalty as you need to fake generics with void* and function pointers (or, in more complex cases, vtables).
However, a sufficiently smart optimizer can get back most (potentially all) of the performance benefits of templates, but (in the absence of link-time optimization) only if the relevant function definitions are visible in the current translation unit.
While this could be achieved by putting static definitions in headers, this might increase code size to unacceptable levels in the same way that C++ templates might.
In contrast, with a C99 inline function, the compiler is free to ignore the inline definition in favour of the external one, which could even reside in a shared library.
A good example of a function that would benefit from this is qsort(), with an inline definition in stdlib.h and an external one in libc.so. There's no a priori reason for qsort() to be slower than std::sort().

multiple definition of inline function

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 units main.cpp and tran.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 and tran.o) and create an executable a.out, the output obtained is:
500
6
700
Why 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 expected 5,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.
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 of func1.
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 to tran.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.
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 meant include 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
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.
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.
The compile error you see is actually a linker error.
gcc and g++ are treating static inline a little differently. inline was first part of C++ and then made into an extension to many C compilers, before being added to standard C. The standard semantics could be different, but it could just be the implementations that are different.
It could also have something to do with some crazy stuff that happens with C++ code that gets rid of duplicate template stuff catching other duplicate stuff as well.
basically Inline is a late entry to GCC ( I mean c compiler).
"[ . . . ] An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition."
— ISO 9899:1999(E), the C99 standard, section 6.7.4

Resources