Confusion over inline behavior C++ - c++

I am learning C++ and I am confused by inline behavior. On cppreference I found that " function included in multiple source files must be inline". Their example is the following:
// header file
#ifndef EXAMPLE_H
#define EXAMPLE_H
// function included in multiple source files must be inline
inline int sum(int a, int b)
{
return a + b;
}
#endif
// source file #2
#include "example.h"
int a()
{
return sum(1, 2);
}
// source file #1
#include "example.h"
int b()
{
return sum(3, 4);
}
This is a bit confusing to me - I thought that the ifndef guard was doing this job exactly, i.e. preventing problems when the same file was included multiple times. In any case, I wanted to test this, so I prepared the following:
// Sum.h
#ifndef SUM_H
#define SUM_H
int sum(int a, int b);
#endif
// Sum.cpp
int sum(int a, int b){
return a + b;
}
// a.h
#ifndef A_H
#define A_H
int af();
#endif
// a.cpp
#include "sum.h"
int af(){
return sum(3, 4);
}
// b.h
#ifndef B_H
#define B_H
int bf();
#endif
// b.cpp
#include "sum.h"
int bf(){
return sum(1, 2);
}
// main.cpp
#include "sum.h"
#include "a.h"
#include "b.h"
#include <iostream>
int main() {
std::cout << af() + bf();
}
And this works fine as expected. Then I use define the sum function to be inline in sum.cpp and sum.h, and it fails to compile:
"sum(int, int)", referenced from:
bf() in b.cpp.o
af() in a.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can somebody clarify this for me?

The include guard with #ifndef/#define/#endif or with #pragma once only prevents the inclusion for every single translation unit.
Lets assume you have a header like:
#pragma once
void Do() {}
and two *.cpp files which do the include. If you now compile with
g++ source1.cpp source2.cpp
you will get a
multiple definition of Do() in xy line/file
Every source file will compiled "alone" and so the guard is not seen from the second translation unit which was set by the first one. Both translations ( compilations ) are done fully independent. As this, the include guard will not protect anything in this case.
For this it is possible to define a function definition as inline. Now both definitions will be presented to the linker but marked as "weak". The linker now did not complain about the two definitions and only takes one of them ( typically the last! ) which is not important, as both are the same in that case.
So the include guard has the sense, that you can include a file multiple times to one translation unit. This will happen typically only if you indirect include a header. Lets say a.h has the function definition and b.h and c.h each include a.h. If your cpp-file includes now b.h and c.h both of them include a.h. So you have, without include guard, multiple definitions. This is the use case for include guards.
And the opposite problem having a "undefined symbol" if the function is defined inline but not visible in all using translation units:
Example:
Having that file:
inline void sum() {}
void f1() { sum(); }
and compile with -O0 produces, output of nm f1.o|c++filt
0000000000000000 T f1()
0000000000000000 W sum()
We see the symbol for sum defined as weak, so it can be present multiple times in link stage. It will also be used if a second translation unit which did not "see" the definition, will be linked without problems.
But using "-O3" you get:
0000000000000000 T f1()
That is implementation specific to the compiler! A compiler can provide inlined functions. Typically they do not, if higher optimization levels are in use.
As a rule: If a function is defined inline, its definition must be visible to every translation unit before it is used there!

Then I use define the sum function to be inline in sum.cpp and sum.h, and it fails to compile:
When a function is declared inline, its definition must be available in all the translation units that use the function. Defining the function in only one translation unit is not correct. That's why you are seeing the linker errors.
Move the definition of the function to sum.h to resolve the linker errors.

You should read documentation carefully, beside the statement:
function included in multiple source files must be inline
it also says this:
2) The definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed (not necessarily before the point of access).
which you violated in your example hense the error.

Related

XCode 6 preprocessor directive ( #ifndef ) not working, can't use nested headers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm having troubles with nested headers,
a.h
#ifndef a_h
#define a_h
#include<b.h>
#endif
b.h
#ifndef b_h
#define b_h
#include<a.h>
#endif
Looks like the include guards are not working.
In fact, I'm getting Apple Mach-O Linker Error, duplicate symbols, clang: error: linker command failed with exit code 1.
What am I doing wrong?
It is highly unlikely that include-guards don't work with an C++ compiler. It is way more likely that your header file(s) contain definitions of objects or functions rather than only declarations thereof. Without seeing the offending content of the files it is impossible to tell what is the case exactly but most likely you have a setup along those lines:
// a.h
#ifndef INCLUDED_A
#define INCLUDED_A
#include "b.h"
int e;
#endif
// b.h
#ifndef INCLUDED_B
#define INCLUDED_B
#include "a.h"
int f() { return 17; }
#endif
// c.cpp
#include "a.h"
// d.cpp
#include "d.h"
The problem is that the symbols e and f are definitions. When including the header(s) into a translation unit, e.g., c.cpp and d.cpp, you'll get them defined in each of the resulting object files. That has nothing to do with the include guards: the include guards only affect the completion of one translation unit and, e.g., prevent that the compiler tries to expand them recursively in each of the header files.
Header files cannot contain definitions of objects or functions (unless they are made inline explicitly or implicitly for some reason). Instead, the headers should contain _declarations. For example, these are declaration of e and f:
extern int e;
int f();
Note that this is also a definition:
extern int f() { return 17; }
A function declaration which contains a body is a definition even if the declaration is preceded by the extern keyword. On the other hand, every declaration of a function without a body isn't a definition, independent on whether it is preceded by the extern keyword.
To fix your problem you need to move the definitions leading to duplicated symbols into a suitable .cpp file. I'd define anything declared in a.h in the file a.cpp.

C++ static bool variable

I can't understand something that causes LNK2005 errors that I've encountered.
Assume that you have a class A:
File A.h:
#ifndef A_H
#define A_H
class A{
public:
static foo(void);
private:
static bool m_someVar;
};
bool A::m_someVar = false;
#endif
File A.cpp:
#include "A.h"
void A::foo(){
m_someVar = true;
}
The code above causes a LNK 2005 however the following code doesn't:
File A.h:
#ifndef A_H
#define A_H
class A{
public:
static foo(void);
private:
static bool m_someVar;
};
#endif
File A.cpp:
#include "A.h"
bool A::m_someVar = false;
void A::foo(){
m_someVar = true;
}
Can someone explain why is this happening even though I have include guards? Should I also add #pragma once?
Thanks in advance.
EDIT: here's the compilation error:
"error LNK2005: "private: static bool GameManager::m_isGameOver" (?m_isGameOver#GameManager##0_NA) already defined in Execution.obj"
include guards(both #ifndef and #pragma) doesn't work across compilation units, which is one of the reasons you should never ever ever define anything in a header file, only declare them. Except for templates of course.
A compilation unit is one .cpp-file and all included headers. Each .cpp create an object file containing a middle stage binary representation of the code, this is the compilation stage. These object files are then linked together in the linking stage. Since each .cpp is handled separately in c++ if you have "float foo;" in header.hpp and both a.cpp and b.cpp include header.hpp, how would the compiler know which foo you mean when running the application?
A "static" variable inside a class declaration is actually a declaration for an extern variable that is in the scope of that class. Like every extern variable, it needs a definition in exactly one source file. Otherwise, the linker will complain about it.
You probably include the .h file from more than one source file, so you have more than one definition.

Circular include statements leading to link error

I have a large project (20+ files) but I managed to set up this small example which recreates my problem. Essentially I have one file (A.cpp) including a second file (B.cpp), but that second file needs several of the variables and functions from the first file. Observe:
A.h:
#ifndef _A_H_
#define _A_H_
static void foo(int _something);
#endif // #ifndef _A_H_
A.cpp:
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
static void foo(int _something)
{
cout << _something << "\n";
}
int main(int argc, char *argv[])
{
B *b;
foo ( 123 ); // So we don't get that pesky defined-not-used warning
b = new B ();
b->display ( 123 );
}
B.h:
#ifndef _B_H_
#define _B_H_
#include "A.h"
class B
{
public:
B();
~B();
void display ( int x );
};
#endif // #ifndef _B_H_
B.cpp:
#include "B.h"
void B::display ( int x )
{
foo ( x );
}
And I am compiling it like so, g++ -Wall A.cpp B.cpp -o main but then I get this error:
A.h:3:13: warning: ‘void foo(int)’ used but never defined [enabled by default]
/tmp/ccFwfZa6.o: In function `main':
A.cpp:(.text+0x54): undefined reference to `B::B()'
/tmp/ccM8SNBK.o: In function `B::display(int)':
B.cpp:(.text+0xd): undefined reference to `foo(int)'
collect2: ld returned 1 exit status
I can tell it's a link error, but I can't tell why I am getting that error.
EDIT:
In my original code I am still getting an error, this time it's about the multiple definition of an integer, here is the error I am getting:
B.o:(.bss+0x4): multiple definition of `some_var'
A.o:(.bss+0x4034): first defined here
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
and I am creating the variable some_var like so
A.h:
#ifndef _A_H_
#define _A_H_
static void foo(int _something);
int some_var;
#endif // #ifndef _A_H_
How is it possible that some_var would get defined more than once when I have those conditional guards?
You have no B::B() body at all. Add one, and don't forget about destructor.
Also, remove static from foo().
The problem now is that each source file that #includes a.h gets a definition of int some_var;. In general, variables should be declared in headers and defined in one source file. So in your header you need
extern int some_var;
and in one source file (presumably a.cpp)
int some_var;
Thanks to Pete Becker I figured out the problem, and it stemmed mostly from a lack of understanding of all things C/C++.
extern statements are not meant to only be used in header files referencing other header files (ie. in "B.h" writing extern int a where a is defined in "A.c") but also in the original header files (in this case "A.h")
I thought, incorrectly, that a definition needed an equals sign (ie. int a = 1) whereas int a is also a definition. I was, thus, defining my variable in "A.h" when I should have been declaring it like so extern int a in "A.h".
After fixing the above 2, I kept getting undefined reference to a (I literally thought the compiler and linker were taking the piss). I was searching for int a=... in "A.cpp" and as clear as day it was being defined. Turns out this definition was inside a function, and therefore was never being defined.
If all else fails, edit your source files in a trivial way (ie. delete a word and type it again) to force a compilation) as I find changing the header files does not always result in full compilations.

C++ I have a function used in all my headers

I have a function that is the same across all my header files and main.cpp if I define it in main.cpp will they all be able to use it once they are included or will they have a compiler issue?
Still new to this whole header file business. Thanks in advance.
In the header file (myfunction.h), you need to have only declaration of the function:
int foo(int param);
In the main.cpp (or any other cpp file - better choice would be myfunction.cpp - just make sure definition is included in exactly one file!) file, you need to have definition of the function:
int foo(int param)
{
return 1;
}
In all other source (cpp) files where you're using function foo, just include myfunction.h and use function:
#include "myfunction.h"
void someotherfunction()
{
std::cout << foo(1) << std::endl;
}
Compiler only needs to see declaration of the function before it is used. Linker will connect definition of the function with the places you've used the function. If you forget to write definition in main.cpp file, you will not get compiler, but a linker error. It may be worth of mentioning that compiler is compiling each cpp file separately, and linker's job is to combine all compiler object files and to produce final output file. On most setups, linker will be called automatically after compiling, so you may not be familiar with it.
If you include entire function definition in the header file, that definition will be compiled in each translation unit where header file is included, and you will get multiple symbol definition linker error, or something similar - that's why you need to include only declaration of the function inside header file. However, there are exceptions for this - for example, you may declare your function inline - other answers explain this approach.
So, now myfunction.h contains the function declaration:
#ifndef MY_FUNCTION_H
#define MY_FUNCITON_H
// declaration
int myfunction();
#end if
myfunction.cpp contains the function definition:
int myfunction()
{
return 4;
}
Now, in file1.cpp and in file2.cpp you want to use this function, so you're including myfunction.h:
// file1.cpp
#include "myfunction.h"
// somewhere in the file
void foo()
{
std::cout << myfunction();
}
... and in the second file:
// file2.cpp
#include "myfunction.h"
// somewhere in the file
void bar()
{
/// ...
std::cout << myfunction();
}
Header files in C and C++ are a language artifact. They are the consequence of the fact, that C and C++ can be implemented as a single-pass compiler. In contrast, Pascal - for example - has a two-pass compiler, that skips over unknown entities during the first pass, and fills in the missing bits in a second pass. Consequently, in C and C++ every type, object, and method must be declared before it can be used. This is the main responsibility of header files.
Header files are expanded into any file that includes them. In other words: The preprocessor replaces the statement #include "foo.h" with the contents of the file "foo.h". With this being the case you need to be careful to not violate the single definition rule: An entity must not be defined more than once.
To meet both requirements you have two options: Declare and define the function in the header, using the inline keyword, or declaring it in the header only, and defining it in another compilation unit.
The following code illustrates both solutions:
// foo.h
inline void foo() {
// Method is implemented in this header file.
// It is marked 'inline' to prevent linker errors
// concerning multiply defined symbols.
...
}
Delaration in header only, implementation in another compilation unit:
// foo.h
extern void foo();
// foo.cpp (or another compilation unit)
void foo() {
...
}
Regardless of which solution you go with, you can use foo() from any compilation unit. If you want to use it from "main.cpp" the code would look something like this:
// main.cpp
#include "foo.h"
int main() {
foo();
}
So you have a function which is used in all your header files, why don't you make a utility.h which keeps track of these types of functions and inline the functions in the .h ?
Declare the function prototype in a custom header file:
int add(int a, int b);
let say header file name is myfunction.h and include it wherever you need the function.
now you can define a function on another.cpp or main.cpp
int add(int a, int b){
return a+b;
}
include your custom header file like this:
#include "myfunction.h"
remember your main.cpp and other cpp files and the new header file should be in the same path.
If you have two files:
main.cpp
#include "func.h"
int main(){
hello();
std::cout<<" world!\n";
return 0;
}
& func.h
#ifndef FUNC_H
#define FUNC_H
#include <iostream>
void hello(void){
std::cout<<"hello";
}
#endif
iostreams objects and functions e.t.c will work fine from within main.cpp.
This posts answers sum up #ifndef pretty well if you would like to know more.

Apple Mach-O linker command failed with exit code 1

I'm using Xcode to build a C++ project.
But I don't understand the error message:
"Apple Mach-O linker command failed with exit code 1"
I found that #include is the reason.
I have two .cpp file which include a same .h file. If I remove #include of one, it will be build successfully.
Other header files are fine expect the header file described above. I already used "ifndef".
#ifndef include guards only work at the level of the translation unit (usually a single source file).
If you define the same object twice in two translation units, that won't be fixed by include guards but the linker will complain bitterly when you try to combine the two object files into a single executable.
I suspect your situation is akin to:
hdr.h:
#ifndef HDR_H
#define HDR_H
void rc(void);
int xyzzy;
#endif
prog1.c:
#include "hdr.h"
#include "hdr.h"
int main (void) { rc(); return xyzzy; }
prog2.c:
#include "hdr.h"
void rc(void) { xyzzy = 0; }
In a situation like that, the include guard will prevent the header being included twice in prog1.c but it will still be included in both prog1.c and prog2.c, meaning that each will have a copy of xyzzy.
When you link them together, the linker will not like that.
The solution is to not define things in headers but to merely declare them there, leaving the definition for a C file:
hdr.h:
#ifndef HDR_H
#define HDR_H
int rc(void);
extern int xyzzy; // declare, not define
#endif
prog1.c:
#include "hdr.h"
#include "hdr.h"
int main (void) { rc(); return xyzzy; }
prog2.c:
#include "hdr.h"
int xyzzy; // define
int rc(void) { xyzzy = 0; }
Declarations are things like function prototypes, extern variables, typedefs and so on (simplistically, things that declare something exists without actually creating an "object").
Definition are things that create "objects", like non-extern variables and so on.
You need to track down what "object" is being defined twice (the linker output should have something like doubly-defined symbol 'xyzzy') and then make sure it's not defined in the header.