unpredictable behavior of Inline functions with different definitions - c++

I have the following source files:
//test1.cpp
#include <iostream>
using namespace std;
inline void foo()
{
cout << "test1's foo" << endl;
}
void bar();
int main(int argc, char *argv[])
{
foo();
bar();
}
and
//test2.cpp
#include <iostream>
using namespace std;
inline void foo()
{
cout << "test2's foo" << endl;
}
void bar()
{
foo();
}
The output:
test1's foo
test1's foo
Huh??? Ok, so I should have declared the foos static... but shouldn't this kind of thing generate a linker error, or at least a warning? And how does the compiler "see" the inline functions from across compilation units?
EDIT: This is using gcc 4.4.1.

You are running into the one-definition-rule. You are not seeing any error because:
[Some] violations, particularly those that span translation units, are not required to be diagnosed
What going on under the covers is that the compiler is not inlining those functions (many compilers will not inline a function unless the code is compiled with the optimizer). Since the function is inline and can appear in multiple translation units, the compiler will mark the function as link-once which tells the linker that it not treat multiple definitions as an error but just use one of them.
If you really want them to be different, you want a static function.

R Samuel Klatchko's answer is correct, but I'll answer part that he didn't.
"And how does the compiler "see" the inline functions from across compilation units?"
It doesn't. It sees the external definitions of functions that are declared not to be static. For such functions, the compiler can inline if it wishes but it also has to generate code callable from outside.

The inline function is placed in a COMDAT section. That's a signal to the linker that it is free to pick any one of the multiple definitions it encounters. You'll get another output message when you reverse the link order.
Another way to place definitions in a COMDAT section (compiler allowing) is:
__declspec(selectany) int globalVariableInHeader = 42;
Which is handy to avoid the "extern" song and dance. Clearly, this mechanism was designed to allow multiple definitions introduced by one header file getting #included by multiple source files to be resolved by the linker. Fwiw, MSVC has the exact same behavior.

Related

What happens when there are two functions with the same signature in the same namespace?

As far as I understand, I can use namespaces to avoid functions overriding each other. But what if the namespaces have the same names?
I included both of the .h files below, called VideoLibrary::check() and it compiles. Why? Doesn't it contradict the purpose of namespace?
file1.h and file2.h:
namespace VideoLibrary
{
void check();
}
file1.cpp:
namespace VideoLibrary
{
void check()
{
printf("check1");
}
}
file2.cpp:
namespace VideoLibrary
{
void check()
{
printf("check2");
}
}
I'm concerned mostly because my project includes external libraries, and i'm worrying it includes functions with the same signature as in my project. How can I get any error for such a case in compilation time?
I'm using Xcode as an editor if it matters.
If you have 2 (non inline) definitions of the same function in different translation unit, you have an ODR (One definition rule) violation NDR (No diagnostic require).

Defined multiple times for the inline function, how possible?

The following quote from c++ primer book confuse me a lot
Unlike other function, inline and constexpr functions may be defined
multiple times in the program. After all, the compiler needs the
definition, not just the declaration, in order to expand the code.
However, all of the definitions of a given inline or constexpr must
match exactly. As a result, inline and constexpr functions normally
are defined in headers.
-- C++ primer 5th Ed, 240 pp
"may be defined multiple times in the program" This quote confuse me a lot. As far as I understand, declaration can be made multiple time, but definition is only needed once.
can someone give me an example why there is a multiple definition.
In a header file (lets call it foo.h) you can have
inline int foo() { /* do stuff */ }
Now if you include foo.h in a couple cpp files then foo will be defined in each of them, which would be a multiple definition error. Since foo is marked as inline though, it is okay because all of the definitions are the same.
As far as I understand, declaration can be made multiple time, but definition is only needed once
The compiler works on translation units (basically a cpp file) and in it, it can do all sorts of optimizations but function inlining and constexpr require that the compiler know the definition of the function. That means each translation unit needs the definition of the function in it. We use inline to make that okay, otherwise it would be a multiple definition error.
As an example. This version isn't valid.
// main.cpp
inline int square(int num) {
return num * num;
}
inline int square(int num) {
return num * num;
}
int main()
{
return square(2);
}
https://godbolt.org/z/nlSbxg
But when you have it in multiple .cpp files (aka. translation units) it is ok because it is now linker job to do right thing.
// b.cpp
inline int square(int num) {
return num * num;
}
// main.cpp
inline int square(int num) {
return num * num;
}
int main()
{
return square(2);
}
Build: gcc main.cpp b.cpp
Same way works #include it will place code in those .cpp files that's all.
Of course if body of function is inlined, then nothing to link so no problem :)
If compiler decides to do an out-of-line version you end up with more than one object file (.o) having definition for the same "inline" function. Such definition will be marked.
Thanks to that mark linker won't yield that it has found multiple definitions and just pick first one that it finds.
So if all definitions are truly the same, then fine! We will get into troubles if we have different body of such function. Example in file b.cpp
// b.cpp
inline int square(int num) {
return 1;
}
It is undefined behavior to have multiple different definitions of the same inline function. It will compile of course but what we get? It depends on linker choice :D
I think the problem is that there are multiple things we can mean by "define." When you write an inline function in a header file, it's "defined" just once in the sense that there is only a single function with that name in your source code.
But that's not how the compiler and linker see the world. If you have an inline function foo in a header file that's called from a.cpp and b.cpp, then the complete compiled version of that function will be included in both a.obj and b.obj. The linker resolves the issue by picking just one of those compiled versions to include in your final binary.
Note that I'm glossing over significant details here, but this is the general idea (and what I think your textbook is eluding to).

One Definition Rule - Multiple definition of inline functions

I was reading ODR and as the rule says "In the entire program, an object or non-inline function cannot have more than one definition" and I tried the following...
file1.cpp
#include <iostream>
using namespace std;
inline int func1(void){ return 5; }
inline int func2(void){ return 6; }
inline int func3(void){ return 7; }
int sum(void);
int main(int argc, char *argv[])
{
cout << func1() << endl;
cout << func2() << endl;
cout << func3() << endl;
cout << sum() << endl;
return 0;
}
file2.cpp
inline int func1(void) { return 5; }
inline int func2(void) { return 6; }
inline int func3(void) { return 7; }
int sum(void) { return func1() + func2() + func3(); }
It worked as the rule says. I can have multiple definition of inline functions.
What is the difference between non-inline function linkage and inline function linkage?
How the linker differentiate between these two?
Making a function inline does two things (the second point is more relevant to your question):
It is a suggestion by the programmer to the compiler, to make calls to this function fast, possibly by doing inline expansion. Roughly, inline expansion is similar to treating the inline function like a macro, expanding each call to it, by the code of its body. This is a suggestion - the compiler may not (and sometimes cannot) perform various optimizations like that.
It specifies the scope of the function to be that of a translation unit. So, if an inline function appears in foo.cpp (either because it was written in it, or because it #includes a header in which it was written, in which case the preprocessor basically makes it so). Now you compile foo.cpp, and possibly also some other bar.cpp which also contains an inline function with the same signature (possibly the exact same one; probably due to both #includeing the same header). When the linker links the two object files, it will not be considered a violation of the ODR, as the inline directive made each copy of the file local to its translation unit (the object file created by compiling it, effectively). This is not a suggestion, it is binding.
It is not coincidental that these two things go together. The most common case is for an inline function to appear in a header #included by several source files, probably because the programmer wanted to request fast inline expansion. This requires the translation-unit locality rule, though, so that linker errors shouldn't arise.

Including .cpp files

I have read in places like here that you have to include .h files and not .cpp files, because otherwise then you get an error. So for example
main.cpp
#include <iostream>
#include "foop.h"
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
foop.h
#ifndef FOOP_H
#define FOOP_H
int foo(int a);
#endif
foop.cpp
int foo(int a){
return ++a;
}
works, but if I replace #include "foop.h" with #include "foop.cpp" I get an error (Using Dev C++ 4.9.9.2, Windows):
multiple definition of foo(int)
first defined here
Why is this?
What include does is copying all the contents from the file (which is the argument inside the <> or the "" ), so when the preproccesor finishes its work main.cpp will look like:
// iostream stuff
int foo(int a){
return ++a;
}
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
So foo will be defined in main.cpp, but a definition also exists in foop.cpp, so the compiler "gets confused" because of the function duplication.
There are many reasons to discourage including a .cpp file, but it isn't strictly disallowed. Your example should compile fine.
The problem is probably that you're compiling both main.cpp and foop.cpp, which means two copies of foop.cpp are being linked together. The linker is complaining about the duplication.
When you say #include "foop.cpp", it is as if you had copied the entire contents of foop.cpp and pasted it into main.cpp.
So when you compile main.cpp, the compiler emits a main.obj that contains the executable code for two functions: main and foo.
When you compile foop.cpp itself, the compiler emits a foop.obj that contains the executable code for function foo.
When you link them together, the compiler sees two definitions for function foo (one from main.obj and the other from foop.obj) and complains that you have multiple definitions.
This boils down to a difference between definitions and declarations.
You can declare functions and variables multiple times, in different translation units, or in the same translation unit. Once you declare a function or a variable, you can use it from that point on.
You can define a non-static function or a variable only once in all of your translation units. Defining non-static items more than once causes linker errors.
Headers generally contain declarations; cpp files contain definitions. When you include a file with definitions more than once, you get duplicates during linking.
In your situation one defintion comes from foo.cpp, and the other definition comes from main.cpp, which includes foo.cpp.
Note: if you change foo to be static, you would have no linking errors. Despite the lack of errors, this is not a good thing to do.
You should just include header file(s).
If you include header file, header file automatically finds .cpp file.
--> This process is done by LINKER.
Because of the One Definition Rule (probably1).
In C++, each non-inline object and function must have exactly one definition within the program. By #includeing the file in which foo(int) is defined (the CPP file), it is defined both in every file where foop.cpp is #included, and in foop.cpp itself (assuming foop.cpp is compiled).
You can make a function inline to override this behavior, but I'm not recommending that here. I have never seen a situation where it is necessary or even desirable to #include a CPP file.
There are situations where it is desireable to include a definition of something. This is specially true when you try to seperate the definition of a template from the declaration of it. In those cases, I name the file HPP rather than CPP to denote the difference.
1: "(probably)" I say probably here because the actual code you've posted should compile without errors, but given the compiler error it seems likely that the code you posted isn't exactly the same as the code you're compiling.
Because your program now contains two copies of the foo function, once inside foo.cpp and once inside main.cpp
Think of #include as an instruction to the compiler to copy/paste the contents of that file into your code, so you'll end up with a processed main.cpp that looks like this
#include <iostream> // actually you'll get the contents of the iostream header here, but I'm not going to include it!
int foo(int a){
return ++a;
}
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
and foo.cpp
int foo(int a){
return ++a;
}
hence the multiple definition error
So I found that if you are compiling from Visual Studios you just have to exclude the included .cpp file from the final build (that which you are extending from):
Visual Studios: .cpp file > right click > properties > configuration properties >
general > excluded from build > yes
I believe you can also exclude the file when compiling from the command line.
I want to clarify something: including header files is not neccessary to make the linker understand what you want. You can just declare it and it will be linked fine.
main.cpp:
#include <iostream.h>
//not including "foop.cpp"!
int foo(int a);
int main(){
std::cout << foo(4) << std::endln;
}
foop.cpp:
int foo(int a){
return a++;
}
I don't encourage doing like this, but know that headers are not some magic which you have to follow to make the code compile.
Using ".h" method is better
But if you really want to include the .cpp file then make foo(int) static in foo.cpp

How do I explain this LNK2005?

So, someone came to me with a project that failed linking with the error LNK2005: symbol already defined in object (using Visual Studio 2010). In this case, I know what is wrong (and hence could point them to the correct solution), but I don't know why this is wrong on a level to give a good explanation about it (to prevent it happening again).
// something.h
#ifndef _SOMETHING_H
#define _SOMETHING_H
int myCoolFunction();
int myAwesomeFunction() // Note implementing function in header
{
return 3;
}
#endif
-
// something.cpp
#include "something.h"
int myCoolFunction()
{
return 4;
}
-
// main.cpp
#include <iostream>
#include "something.h"
int main()
{
std::cout << myAwesomeFunction() << std::endl;
}
This fails linking, and is fixed by putting myAwesomeFunction() into the .cpp and leaving a declaration in the .h.
My understanding of how the linker works comes pretty much from here. To my understanding, we are providing a symbol that is required in one place.
I looked up the MSDN article on LNK2005, which matches how I expect linkers to behave (provide a symbol more than once -> linker is confused), but doesn't seem to cover this case (which means I'm not understanding something obvious about linking).
Google and StackOverflow yield issues with people not including an #ifndef or #pragma once (which leads to multiple declarations of provided symbols)
A related question I found on this site has the same problem, but the answer doesn't explain why we're getting this problem adequately to my level of understanding.
I have a problem, I know the solution, but I don't know why my solution works
In a typical C++ project, you compile each of the implementation (or .cpp) files separately - you generally never pass a header (or .h) file to the compiler directly. After all preprocessing and inclusions are performed, each of these files becomes a translation unit. So in the example you've given, there are two translation units that look like this:
main.cpp translation unit:
// Contents of <iostream> header here
int myCoolFunction();
int myAwesomeFunction() // Note implementing function in header
{
return 3;
}
int main()
{
std::cout << myAwesomeFunction() << std::endl;
}
something.cpp translation unit:
int myCoolFunction();
int myAwesomeFunction() // Note implementing function in header
{
return 3;
}
int myCoolFunction()
{
return 4;
}
Notice that both of these translation units contain duplicate content because they both included something.h. As you can see, only one of the above translation units contains a definition of myCoolFunction. That's good! However, they both contain a definition of myAwesomeFunction. That's bad!
After the translation units are compiled separately, they are then linked to form the final program. There are certain rules about multiple declarations across translation units. One of those rules is (ยง3.2/4):
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.
You have more than one definition of myAwesomeFunction across your program and so you are breaking the rules. That's why your code doesn't link correctly.
You can think of it from the linker's perspective. After these two translation units are compiled, you have two object files. The linker's job is to connect the object files together to form the final executable. So it sees the call to myAwesomeFunction in main and tries to find a corresponding function definition in one of the object files. However, there are two definitions. The linker doesn't know which one to use so it just gives up.
Now let's see what the translation units look like if you define myAwesomeFunction in something.cpp:
Fixed main.cpp translation unit:
// Contents of <iostream> header here
int myCoolFunction();
int myAwesomeFunction();
int main()
{
std::cout << myAwesomeFunction() << std::endl;
}
Fixed something.cpp translation unit:
int myCoolFunction();
int myAwesomeFunction();
int myCoolFunction()
{
return 4;
}
int myAwesomeFunction()
{
return 3;
}
Now it's perfect. There is only one definition of myAwesomeFunction across the whole program now. When the linker sees the call to myAwesomeFunction in main, it knows exactly which function definition it should link it to.
The linker is merely letting you know that you broke the one definition rule. This is a basic, well-documented rule of C++ - it isn't solved by using include guards or #pragma once directives, but, in case of a free function, by marking it inline or moving the implementation to a source file.
When a non-inline method is implemented in a header, all translation units that include that header will define it. When the corresponding .obj files are linked together, the linker detects the same symbol is exported (and defined) multiple times, and complains.
Moving the implementation to a cpp file effectively transforms your initial definition into a declaration.
myAwesomeFunction is defined in two source files: something.cpp and main.cpp. Move its implementation to one of source files, or declare this function as static.