C++ include guards do not seem to be working - c++

I am getting error messages from the mbed C++ compiler that seem to be indicative of malfunctioning include guards.
In main.cpp, I include my header file as follows:
#include "mbed.h"
#include "sample.h"
This is my sample.h:
#include "mbed.h"
#ifndef STUFF_H
#define STUFF_H
/* LEDs */
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
/* Subroutines */
void sweepLEDs();
void pulseLEDs(int numPulses);
void clearLEDs();
#endif
In sample.cpp, I am including sample.h as follows:
#include "sample.h"
In both main.cpp and sample.cpp, I am referring to variables led1, led2, led3, led4 without declaring them. However, the compiler is outputting these complaints:
" Symbol led1 multiply defined (by sample.cpp.cpp.LPC1768.o and main.cpp.cpp.LPC1768.o)."
...
" Symbol led4 multiply defined (by sample.cpp.cpp.LPC1768.o and main.cpp.cpp.LPC1768.o)."
Are my include guards written improperly? Or is there some other issue?
(For reference, here is the link to the mbed.h source)

The issue is a misunderstanding of what include guards do. Include guards prevent the compiler from seeing the same content again in the same translation unit (for the same .cpp file). They do not prevent separate translation units from seeing the same code.
In your header file, you define (not just declare) the variables. Therefore every translation unit which includes the header creates its own copy of those variables.
The correct way to do it is to define the variables in a .cpp file and only declare them in the header (the include guards should be there anyway, to prevent multiple inclusion in the same translation unit).
That is, in your file sample.h, prefix your variables with extern and remove the initializer (so they are only declared, not defined), and define them in the corresponding .cpp file (the one where also the functions are defined), by putting the exact definitions from your header there.
In an unrelated note, you should put the #include "mbed.h" in sample.h inside the include guards, because some compilers optimize compile speed for such guards, and that optimization doesn't work if there's material outside the include guards. Note that this is not really a correctness issue (assuming mbed.h is properly protected by include guards as well), but a compiling performance issue.

You need to mark the declarations as "extern" like this:
extern DigitalOut led1;
Then define them (i.e. allocate storage for them) in sample.cpp by using the expression you used to have in the header.

Related

Mutliple header & source files in cpp, pretty sure a duplicate thread [duplicate]

I have a header file "USpecs.h":
#ifndef USPECS_H
#define USPECS_H
#include "Specs.h"
#include <iostream>
#include <vector>
std::vector<Specs*> UcakSpecs;
#endif
I am using this header both in main function and another class named Ucak.
But when i build it the following error occurs:
Ucak.cpp|6|multiple definition of `UcakSpecs'|
As i searched before, it should be okay with #ifndef but it is not.
The include guards only prevent multiple definitions within a single translation unit (i.e. a single source file with its included headers). They do not prevent multiple definitions when you include the header from multiple source files.
Instead, you should have a declaration in the header:
extern std::vector<Specs*> UcakSpecs;
and a definition in one (and only one) source file:
std::vector<Specs*> UcakSpecs;
Inclusion guards only prevent the header from being included in the same translation unit more than once. If you include this header in multiple translation units, you will have multiple definitions of UcakSpecs across the program.
The way to declare a global variable is to declare it as extern in the header file:
#ifndef USPECS_H
#define USPECS_H
#inclde "Specs.h"
#include <iostream>
#include <vector>
extern std::vector<Specs*> UcakSpecs;
#endif
A global variable declared as extern is only a declaration.
Then make sure it is only defined in a single translation unit by defining it in an implementation file (perhaps in USpecs.cpp);
std::vector<Specs*> UcakSpecs;
The #ifndef only applies to a single compilation unit. Since you have two (the main function and Ucak class), the variable is defined twice.
Consider declaring the variable as extern in the header file:
extern std::vector<Specs*> UcakSpecs;
and defining it inside the Ucak.cpp file:
std::vector<Specs*> UcakSpecs;
This should work.

method already defined (template class)

I am getting the error "method already defined in class.obj" on ALL my methods,
I've seen that some of the solutions include separating the class into a header and a .cpp file but it's not possible in this case.
Any help will be much appreciated.
this is my h file: http://pastebin.com/k46JEQBH
the cpp has:
#include "stdafx.h"
#include "poly.h"
The problem is your definitions are in your header, and it's probably being included in multiple .cpp files. Each .cpp file is a new translation unit. Imagine you compile each .cpp file one at a time. For each .cpp file that includes your header, it will be the first time that header is encountered, POLY_H will not have been defined yet. Declarations are allowed to appear multiple times, but definitions are not. Move your definitions to a separate .cpp file and everything should work.
Edit: Keeping the definition in your header is necessary and allowed for template classes, but your class is not templated.
Could it be your usage of #pragma once? What compiler are you using?
And have you tried using include guards instead to see if that resolves the errors? For example:
#ifndef POLY_H
#define POLY_H
//your code minus the pragma once
#endif //POLY_H

What is the scope of pre-compiler define in c++?

Is the scope of the pre-compiler define the file where it defined?
for example:
three files :
test1.hpp/test1.cpp
test2.hpp/test2.cpp
test3.hpp/test3.cpp
An within test1.cpp:
#ifndef test1_hpp
#define test1_hpp
// some declarations
#endif
test2.hpp and test.hpp both #include test1.hpp. If the scope of test1_hpp is the whole application, as far as I understand, there can only one include test1.hpp success. Because once included, test1_hpp is defined.
test2.hpp and test.hpp both #include test1.hpp. If the scope of test1_hpp is the whole application, as far as I understand, there can only one include test1.hpp success. Because once included, test1_hpp is defined.
The compiler works on translation units (think: individual .cpp files) not the whole application (think: executable). What you call "the scope of the pre-compiler define" is the current translation unit. In your example, the // some declarations part in test1.hpp would be visible/processed in each of the CPPs that include test1.hpp directly or indirectly i.e. in all of test1.cpp (directly), test2.cpp, test3.cpp (indirectly, via both #include test1.hpp).
The #ifndef test1_hpp is a common idiom to prevent inadvertent inclusion of the same header file multiple times within the same translation unit - see for example "Use of #include guards" on Wikipedia.
Your assumption is correct. If you use the #ifndef guard in your header, the first time that test1.hpp is included in your application by the pre-processor, test1_hpp will be defined and will allow the inclusion of the code in your header. In future includes of test1.hpp, the code won't be re-included thanks to the guard.
This is needed, in most part, to prevent double definitions upon including the header in multiple files of your project, and comply with the one definition rule.

c++ header file redefenition error

*note: I am new to c++, so sorry if I make an obvious mistake.
I am getting an error on all of my variables. I am trying to use headers and forward declarations. Here is a snippet of my code:
//BotRenderer.h
#ifndef BOTRENDERER_H_
#define BOTRENDERER_H_
#include <SDL2/SDL.h>
SDL_Texture *botTextures[217];
int currentBotFrame;
//BotRenderer.cpp
#include "BotRenderer.h"
SDL_Texture *botTextures[217];
int currentBotFrame = 0;
All of the lines with variables give the error, '[variable name here] previously declared here'. What can I do to fix this?
The problem is that include guards only protect against multiple inclusion in the same translation unit (source file).
If you define a variable in a header file and include it in more than one source file then the variable will be defined in both source files (translation units), and when you then link the generated object files together the linker will notice that the variable is defined in both object files and give you an error.
What you should do is declare the variables in the header file, the easiest to do it is to add the extern keyword before the declaration, like
extern SDL_Texture *botTextures[217];
extern int currentBotFrame;
Regarding your compiler error, you get it just because you define the variables in both the header file and in the source file. The solution you your problem is the same, declare in header file and define in source file.
You should read about the One Definition Rule (a.k.a. ODR).

Multi Including a .h File

In an .h file, I am declaring a global variable as:
#pragma data_seg(".shared")
#ifndef DEF_VARX
#define DEF_VARX
int VARX=0;
#endif /*DEF_VARX*/
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")
However if I include this file in multiple cpp files, when I try to compile, I get " error LNK2005: "int VARX" (?VARX##3HA) already defined in Dll.obj" error. If I include in only one cpp file, no problem is encountered.
Isn't #IFNDEF.... check enough for preventing this? Am I missin something?
The reason of this behavior is, that you compile the line
int VARX=0;
into each .obj file. Thats OK for compiling, but upon linking the symbol becomes multiply defined, which is illegal. Using
extern int VARX;
in the header file, and
int VARX=0;
in one (and only one) source file resolves this problem.
I think you're supposed to forward declare the variable in the .h and later define it in its shared section in a .cpp, something like:
// in a header file
#pragma once
extern int VARX;
// in a .cpp
#pragma data_seg(".shared")
int VARX=0;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")
The problem is that is that you prevent multiple inclusion of the file for a given translation unit. (for a given say cpp file)
But if several of your cpp include this VARX.H, then you'll have more than one definition for this variable.
Instead, you should only declare the variable in the .H file, but initialize it to 0 in only one location.
Yes, you're missing the extern keyword.
In your header file, use:
extern int VARX;
In a source file, actually declare space for the variable:
int VARX = 0;
ifdef prevents it for a separe object file. When the header is include in several source (cpp) files, VARX will be dedfined in all of them. Consider declaring it as extern in header file, and initialize in one cpp file.
The problem is you must be including the file in multiple compilation units. Let's say you have a.cpp and b.cpp. Both include your header file. So the compiler will compile (and pre-process) separately, so for both files, DEF_VARX is not yet defined. When you go to link the to object files together, the linker notices that there is a name collision.
As others have suggested, the solution would be to declare it 'extern', then place the actual value in a cpp file, so it only is compiled once, and linked to everything without name collisions.