Non inline function defined in header file with guards
#if !defined(HEADER_RANDOM_H)
#define HEADER_RANDOM_H
void foo()
{
//something
}
#endif
Results in linker error : Already defined in someother.obj file
Making the function inline works fine but I am not able to understand why the function is already erroring out in first case.
If the header is included in more than one source file and the function is not marked as "inline" you will have more than one definition. The include guards only prevent multiple inclusions in the same source file.
You're violating the one definition rule. If you want to define a function directly in the header, you must mark it as inline -- that will allow the function to be defined multiple times. Also note that inline has no other meaning, particularly it doesn't force the compiler to inline calls (contrary to popular belief).
Since it is not inline, each translation unit will have its own copy of the function resulting in the function being defined multiple times.
Related
I have read existing answers on the two meanings of inline, but I am still confused.
Let's assume we have the following header file:
// myclass.h
#ifndef INCLUDED_MYCLASS
#define INCLUDED_MYCLASS
class MyClass
{
public:
void foo(); // declaration
};
inline void MyClass::foo()
{
// definition
}
#endif
Why does void foo() which is defined outside the class in the file, have to be explicitly defined with inline?
It's because you defined MyClass::foo in a header file. Or a bit more abstract, that definition will be present in multiple translation units (every .cpp file that includes the header).
Having more than one definition of a variable/function in a program is a violation of the one definition rule, which requires that there must be only one definition in a single program of every variable/function.
Note that header guards do not protect against this, as they only protect if you include the same header multiple times in the same file.
Marking the function definition as inline though means that the definition will always be the same across multiple translation units.1.
In practice, this means that the linker will just use the first definition of MyClass::foo and use that everywhere, while ignoring the rest,
1: If this is not the case your program is ill-formed with no diagnostics required whatsoever.
If you put MyClass::foo() in a header file and fail to declare it inline then the compiler will generate a function body for every compilation unit that #includes the header and these will clash at link time. The usual error thrown by the linker is something along the lines of Multiple definition of symbol MyClass::foo() or somesuch. Declaring the function inline avoids this, and the compiler and linker have to be in cahoots about it.
As you mention in your comment, the inline keyword also acts a hint to the compiler that you'd like the function to be actually inlined, because (presumably) you call it often and care more about speed than code size. The compiler is not required to honour this request though, so it might generate one or more function bodies (in different compilation units) which is why the linker has to know that they are actually all the same and that it only needs to keep one of them (any one will do). If it didn't know they were all the same then it wouldn't know what to do, which is why the 'classical' behaviour has always been to throw an error.
Given that the compilers these days often inline small functions anyway, most compilers also have some kind of noinline keyword but that is not part of the standard.
More about inline at cppreference.
I've done a simple experiment, a ".h" file with a class definition and a funciton definition, as below:
$cat testInline.h
#pragma once
class C{
public:
void f(){}
};
void g(){}
Then 2 users of this .h file:
$cat use01.cpp
#include"testInline.h"
void g01(){
g();
C obj1;
obj1.f();
}
$cat use02.cpp
#include"testInline.h"
int main(){
g();
C obj2;
obj2.f();
return 0;
}
I compile them together and gets an error:
$g++ use01.cpp use02.cpp
duplicate symbol __Z1gv in:
/var/folders/zv/b953j0_55vldj97t0wz4qmkh0000gn/T/use01-34f300.o
/var/folders/zv/b953j0_55vldj97t0wz4qmkh0000gn/T/use02-838e05.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Looks really weird: I've used "#pragma once",still I cannot stop compiler from reporting duplicated definition of g()(__Z1gv as name mangling)
Then I modified testInline.h->g() definition to be like:
inline void g(){}
Well, it compiles. Isn't it in C++ that "inline" keyword is basically useless, because compilers will decide whether it'll inline a function or not?
And,why C::f() with code in .h file doesn't report duplication, while a C-style function g() does? And why class C doesn't "have to" add "inline" for its "f()" function, while g() has to use "inline"?
Hope I've stated my question clearly. Thanks for your help.
I've used "#pragma once",
Yes, you did. And each one of the two translation units effectively processed the header file exactly once. Each one would've done so even without the pragma, since each translation unit includes the header file just once.
#pragma once does not mean "include this header file in just one of the translation units being compiled". It means "include this header file once per translation unit, even if the translation unit directly, or indirectly, includes the header file two or more times". As such, each translation unit included the header file, and defined the functions/methods from the header file itself. Since the same function or method ended up being defined by both translation units you ended up with a duplicate at link time.
Isn't it in C++ that "inline" keyword is basically useless, because
compilers will decide whether it'll inline a function or not?
It is true that the compiler decides whether the function actually gets inlined, or not. However, the inline keyword specifies whether the function definition is processed as if it were logically inlined for every use of it, and not actually defined. As such, using the inline keyword does not result in duplicate definitions since, logically, the function is inserted inline at its every reference.
It is true that Whether this actually happens, or whether the compiler produces non-inlined code, is up to the compiler. However, C++ requires that the function gets compiled "as if" it was inlined; so even if the compiler decides not to inline the function, it must take whatever steps are necessary to ensure that the duplicate non-inlined copies of the function does not result in an ill-formed program.
And,why C::f() with code in .h file doesn't report duplication,
Because a class method defines inside the definition of the class is effectively an inline definition, even if the inline keyword is not explicitly specified.
The inline keyword is not useless. It's just that it doesn't necessarily control whether the function is actually inlined.
The inline keyword marks a function as possibly defined in multiple translation units. (The definition and meaning must be the same in all of them.) You should mark a function defined in a header file as inline.
A function defined within a class definition, like your C::f, is automatically considered "inline".
I have a big project (400 files) and all of the headers have include guards and everything, however I get 500 LNK2005 errors.
Could it be that I have function bodies defined in some headers? Cause I saw the same things in the DirectX utility headers(DirectXCollision has some of it's functions are completely in the header).
Or could it be because they are using .inl files instead of .cpp?
Could it be that I have function bodies defined in some headers?
Yes, that could be. Defining a function in more than one translation unit results in a duplicated symbol definition error.
You can get around the duplication error by declaring those functions inline. [7.1.2]/2 reads:
A function declaration (8.3.5, 9.3, 11.3) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.
Include guards will only save you from including the same header multiple times into the same compilation unit (one cpp file). If you include the header into a second cpp file and then link them together, both of them will have anything the header brings in. That's why it is usually a bad idea to have function implementations in the headers.
You can work around that by declaring your function inline, then compiler will copy/paste them around.
Do you define global variables in your header files? That can be a cause of the error.
And include guards will not help.
A global variable should be defined only in one translation unit and should be externed in all other translational unit.
For eg.
in x.h, you have
int myVar;
Now you #include x.h in both a.cpp & b.cpp,
then you will get a linker error even if you had include guards in x.h
Because now myVar will get defined in both a.obj and b.obj and the linker will find 2 myVars.
Okay, up until now, I thought that functions defined in header files are treated like inline functions, just like template stuff, defined once, and all that.
I also use inclusion guards, yet I still got linker errors of multiple defined objects, and I know that is because of all those different units duplicating stuff the linker tries to pick out which item is the right one.
I also know that inline is merely a suggestion, and might not even get used by the compiler, etc.
Yet I have to explicitly define all those small functions in that little header only toolset I wrote.
Even if the functions were huge, I'd have to declare them inline, and the compiler would still possibly disregard the hint.
Yet I have to define them so anyway.
Example:
#ifndef texture_math_h__
#define texture_math_h__
float TexcoordToPixel(float coord, float dimension)
{
return coord * dimension;
}
float PixelToTexcoord(float pixel, float dimension)
{
return pixel / dimension;
}
float RecalcTexcoord(float coord,float oldDimension, float newDimension)
{
return PixelToTexcoord(TexcoordToPixel(coord,oldDimension),newDimension);
}
#endif // texture_math_h__
Errors are , blabla already defined in xxx.obj, for each unit that includes the file
When I declare all of those inline, it links correctly.
What's the reason for that? It's not a huge problem, and heck, optimizations probably inline stuff found in cpp, too, right?
I'm just curious about the why here, hope it's not too much of a duplicate and thank you for your time.
Inclusion guards only guard against the code being included twice in the same translation unit. So if you have multiple files that include the same header, the code is included multiple times. Functions defined in a header are not inline by default, so this will give you linker errors - you need to define those function with the inline keyword, unless they are member functions of a class.
Also, note that names that contain double-underscores are reserved for the purposes of the C++ implementation - you are not allowed to create such names in your own code.
Member functions are potencially inlined - you can't force inlining! - if (a) they are defined inside the class or if (b) you use the inline-clause in the definition. Note if you are using the inline-clause you shouldn't define the function in the header - the only exception would be templates as these are "special".
As you just updated the question:
Every user of this header will have a definition of the functions -> multiple defintions. You need to separate definition and declaration!
It's all about the one definition rule. This states that you can only have one definition for each non-inline function (along with various other types of entity) in a C++ program across all the translation units that you link in to make the program.
Marking a function inline enables an exception to the usual one definition rule. It states (paraphrased) that you can have one definition of an inline function per translation unit provided that all the definitions match and that a definition is provided in each translation in which the inline function is used.
Include guards will prevent you from accidentally providing more than one definition per translation unit by including the header file containing the definitions multiple times.
To satisfy the one definition rule for a non-inline function you would still have to ensure that there is only one translation unit containing the function definitions. The usualy way to do this is by only declaring the functions in the header file and having a single source file containing the definitions.
While I was reading the accepted answer of this question, I had the following question:
Typically, methods are defined in header files (.hpp or whatever), and implementation in source files (.cpp or whatever).
One of the main reasons it is bad practice to ever include a "source file" (#include <source_file.cpp>) is that its methods implementation would then be duplicated, resulting in linking errors.
When one writes:
#ifndef BRITNEYSPEARS_HPP
#define BRITNEYSPEARS_HPP
class BritneySpears
{
public:
BritneySpears() {}; // Here the constructor has implementation.
};
#endif /* BRITNEYSPEARS_HPP */
He is giving the implementation of the constructor (here an "empty" implementation, but still).
But why then including this header file multiple times (aka. on different source files) will not generate a "duplicate definition" error at link time ?
Inline functions are exceptions to the "one definition rule": you are allowed to have identical implementations of them in more than one compilation unit. Functions are inline if they are declared inline or implemented inside a class definition.
Member functions with implementation inside the class definition are treated as inline functions. Inline functions are exempt from one definition rule.
Specifically when the linker sees two inline functions with the same signature it treats them as if it is the same function and just picks one of them. This can lead to really weird hard to detect problems.
Because it is an "inline" function. Inline functions can be included from headers as many times as you like and they don't cause duplicate definition linker errors.
The compiler will also try to bring them inline so, in your example above, the compiler will try and eliminate the call to the constructor completely.