macro guard doesn't work in header - c++

hey everyone, i got code like this:
//a.h
#ifndef SB
#define SB
namespace A{ int a = 10; int b = 10;}
#endif
however, if I imported the a.h in a.cpp file, the compiler would complain:
error LNK2005: "int A::a" (?a#A##3HA) already defined in a.obj
It looks like compiler would combine .h file and .cpp file together without explicit "import" statement. But it doesn't make sense to me that it would happen with the macro guard defined.
I use Visual C++

#include guards prevent one file from including the same .h file multiple times. They don't prevent multiple files from each including the same .h file once, which is what I assume is happening to you. Move your definitions into a single .cpp file and leave just a declaration here:
namespace A {
extern int a;
extern int b;
}
which tells the compiler that these variables exist somewhere, but their definitions can be found elsewhere.

Chances are you have a cyclic #include statement some where that is putting the header file into both object files and then trying to link the object files together gets the duplicate entries.
Remember that when you #include what the compiler is doing is cut/pasting the contents of the .h file in place of the line the include is on.
You will want to declare prototypes in the .h file, not the actual declaration of those objects and their values.

If you want a and b to have constant values, you can do this:
//a.h
#ifndef SB
#define SB
namespace A{const int a = 10; const int b = 10;}
#endif
and it will not be a problem to include it in several places.
If you need the values to change, you should follow dfan's advice.

Related

error LNK2005: already defined on including a header file twice

I need to edit and access a few variables across multiple cpp files in a visual studio project. So I created a header file with a namespace containing all the variables I require as follows:
namespace windowdimension{
TCHAR openwindows[20][180];
int winnum = 0;
int windowleft = 0;
int windowright = 1360;
INT windowtop = 0;
INT windowbottom = 768;
LONG leftarray[20];
LONG rightarray[20];
LONG toparray[20];
LONG bottomarray[20];
}
However if I #include this header file in two source files, I get this linker error 2005 saying the parameter was already defined in the other obj.
On referring to other question of the same error, I got to know here that
a function definition can only appear once. Every .cpp file that #includes your .h file will generate yet another copy of the function.
But does that hold for namespace variables as well?
If so how do we ensure access to a particular variable across multiple source files?
You should never define global variables in a header file.
To be able to share, you need to declare them in a header file (using extern keyword), and define only once in a .cpp file.
Sure, never forget about include guards in every header file (#pragma once is pretty portable solution):
global.hpp
#pragma once
namespace global {
extern int variable;
}
global.cpp
namespace global {
int variable = 0;
}
Anyway, it is a very bad practice to use global variables.
You probably forgot to add an include guard:
Header.h
#ifndef HEADER_H
#define HEADER_H
namespace something {
}
#endif
Another option is to use #pragma once in the very beginning of your header file.

Why am I getting linking errors even with header guards? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does this not prevent multiple function declarations?
Global.h
#ifndef Global_h
#define Global_h
#include <iostream>
unsigned char exitStatus;
#endif
OutputHandler.h
#ifndef OutputHandler_h
#define OutputHandler_h
#include "Global.h"
class OutputHandler {
private:
static bool instanceExists;
// more code
#endif
Root.h
#ifndef Root_h
#define Root_h
// declarations
OutputHandler *output;
#endif
Root.cpp
#include "Root.h"
// gets instance of OutputHandler
// more code
I am getting errors regarding exitStatus, static bool instanceExists, and static class output being already defined by Root.obj in OutputHandler.obj. I assume the issue is with including the header file OutputHandler.h in both Root.h and OutputHandler.cpp. Anyone know how to fix this or how to better organize header files?
Because include guards only work at the translation unit level (you can, for this simple case, consider a single C file to be a translation unit).
That means a single C file, if it includes the header file twice, will not process it the second time due to the include guards.
However, if you include the header from two different C files, each of them will get a copy of the variables defined in that header.
Then, when you link them together, you get the duplicates.
The easiest way to get around this problem is to never define things in headers, only declare them.
So, in the header (eg, xyzzy.h), you have:
extern int xyzzy; // declare but don't define.
and in all the C files that want to use that, put:
$include "xyzzy.h"
and, in one of those C files, also put:
int xyzzy; // define it here, once.
You can think of declaration as a simple "I declare that this exists somewhere, just not here", while definition is "I an creating this here and now".
Declare extern usigned char exitStatus in Global.h and define it in one implementation file.
The problem is during the linking phase; include guards in the headers won't help you.
In C, there is the separate concepts of declarations and definitions. Declarations are what are put into headers; they merely state that a particular variable exists. The definition of a variable is where storage is actually allocated for it.
For example, in your Global.h, you have:
#ifndef Global_h
#define Global_h
#include <iostream>
usigned char exitStatus;
#endif
This is defining a variable called exitStatus, and the linker is complaining because any given variable should only be defined in one place in a program. What you need to do is declare it in the header, and then define it in only one place in a source (*.cpp) file. For example, your header should declare exitStatus with:
extern char exitStatus;
and in only one source file, define it with:
char exitStatus;
The situation is similar for output in Root.h, as well as any other place you should be declaring variables in the header file.
See also: http://www.cprogramming.com/declare_vs_define.html

Global constants in .h file, linking problems with gcc, works with g++

I have two .c files and one .h file included from them both. In the .h file, I have declared global constants. When building with gcc, I get linking problems, telling me that the constants are defined twice, even though I have
#ifndef __FOO
#define __FOO
const struct foo bar = ...
#endif
I get
/tmp/ccql6KF1.o:(.rodata+0x0): multiple definition of `bar'
However, compiling the very same code with g++ works perfectly. Is there some differences in the way C and C++ treats global constants declared in .h files? What approach should I consider?
Please note that all objects need to share the memory for the constants, since I have limited resources.
You should declare the constant in a .h file and define it in a single .c file:
bar.h:
extern const struct foo bar;
bar.c:
#include "bar.h"
/* do this in a single file */
const struct foo bar = ...;
Then include bar.h everywhere you want to access bar:
something.c:
#include "bar.h"
void doSomethingWithBar() {
struct *foo something = &bar;
...
}
Edit (by Shahbaz): The reason why this works and your code doesn't work is that when you include a file, the contents of that file are copy pasted in place of #include (this is regardless of the file, you can include anything, including files with .h extension is just a convention). So when you say const struct foo bar; in a header file and include it in two files, it's exactly like writing that line in both files, therefore defining the variable in both files and hence the link error.
Your header protection also doesn't work (the
#ifndef __BAR_H__
#define __BAR_H__
... header contents
#endif
) because each of your source files are compiled separately, therefore when bar.h is included in one file and __BAR_H__ defined, when the next file is being compiled this definition of __BAR_H__ is lost.
You should declare only :
const struct foo bar;
and assign it a value in a .c file.

Can I include global static member?

There are few global variables which are static in one of the header files. I see these variables are used in the associated .cc files. So, looks like this has no issues.
My questions are:
Whats the difference between including a global variable vs static global variable ?
I know static global doesnt have visibility outside its file. But dont know how this would work when it comes as part of a .h which is #included.
I wrote a sample program, and tried the same thing. But, I get compilation error the moment I make the variable static. When it is just global, it is fine.
So, is there something which I am missing on a regular g++ build ? (Please note, the initial case was on our official code base which has enough makefiles, .h files and all).
Thanks for the help !
Here is my sample program :
.h file:
#include <iostream>
typedef unsigned int uint;
static const int appk=189;
class abc1
{
public:
abc1(int x);
virtual void printVal();
};
.cc file:
#include "abc1.h"
extern int appk;
abc1::abc1(int x)
{
}
void abc1::printVal()
{
printf("abc1 print: %d\n", appk);
}
(1) If you put a global variable in a .h file and include it in various .cpp/.cc files then it will be defined multiple times for every file. So you are most like to get a linker error.
To overcome that, mostly you are likely to use extern keyword:
// myfile.h
extern int i;
and define that in only one translation unit:
// somefile.cc
int i;
(2) If you put a static global in a .h file and include it, then you will not get any error, because for every different translation unit, there will be a different copy for that static global variable.
// myfile.h
static int i; // creates a unique and unrelated copy in all .cc file where included
However, such usage is deprecated; instead of that it's better to use unnamed namespace:
namespace {
int i;
}
From your question, I don't see that you should get any linker error for static global.
Hard to tell your compilation error without code, but if you have a header that declares a static global, then you just create that global variable independently and separately in each translation unit that includes the header.
Example:
header.h:
#ifndef H_XXX
#define H_XXX
static int a;
#endif
file1.cpp:
#include "header.h"
// now have access to a variable called "a"
file2.cpp:
#include "header.h"
// now also have access to some "a"
The two files both have access to a global variable called a, but each file has its own separate copy, private to its translation unit, which is not visible outside.
For a practical example, I think cout is declared as a static global, so everyone who uses <iostream> gets their own copy.
static variable has internal-linkage. What it means is that if you have a static variable a in x.h and you include x.h in two files say m.cpp and n.pp then each of these two files gets its own copy of a which means if you change its value in m.cpp, then n.cpp is not going to see that change, because there exists two variables with same name in each translation unit (.cpp). And they're independent of each other.
But if a is not static, then including x.h in more than one files, you will get multiple-definition error, because each inclusion of x.h will try to define a, but since a is not static; it has external linkage now, which means if its defined in m.cpp, then you will get error when including x.h in n.cpp (or vice-versa). In this case, you've to write x.h as:
//x.h
extern int a;
And then define a in exactly one .cpp file, either m.cpp or n.cpp, but not both. Say its m.cpp.
//m.cpp
#include "x.h"
int a =10;
And you're done. Now you can include x.h in as many .cpp file as you want, and can access a, modify its value, do whatever you want. Any change to it, will be seen by all .cpp files now.

Using struct in different .cpp file

I have two .cpp files in one project, main.cpp and myfile.cpp
I have globaly defined struct mystruct in main.cpp, now I want to use this struct in myfile.cpp.
When I write mystruct in a header file and include in both cpp files I get an error, saying mystruct redefinition. How should I solve this problem.
If you are trying to share the definition of a struct among several compilation units (cpp files), the common way is this: Place the definition of your struct in a header file (mystruct.h). If the struct contains any methods (i.e. it is rather a class with all member public by default), you can implement them in mystruct.CPP file, or, if they're lightweight, directly within the struct (which makes them inline by default).
mystruct.h:
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
struct MyStruct
{
int x;
void f1() { /* Implementation here. */ }
void f2(); /* Implemented in mystruct.cpp */
};
#endif
mystruct.cpp
#include "mystruct.h"
// Implementation of f2() goes here
void MyStruct::f2() { ... }
You can use your struct in as many cpp files as you like, simply #include mystruct.h:
main.cpp
#include "mystruct.h"
int main()
{
MyStruct myStruct;
myStruct.x = 1;
myStruct.f2();
// etc...
}
If, on the other hand, you are trying to share a global instance of the struct across several compilation units (it's not absolutely clear from your question), do as above but also add
extern MyStruct globalStruct;
to mystruct.h. This will announce that an instance is available with external linkage; in other words that a variable exists but is initialized elsewhere (in your case in mystruct.cpp). Add the initialization of the global instance to mystruct.cpp:
MyStruct globalStruct;
This is important. Without manually creating an instance of globalStruct, you'd get unresolved-external linker errors. Now you have access to globalStruct from each compilation unit that includes mystruct.h.
You should move the common struct to a header file and include that header in both files. Any other solution is a workaround.
The problem is that you basically have the same code twice as a result if you see an include as just a import of the code.
You can use #ifdef to fix it, see http://www.fredosaurus.com/notes-cpp/preprocessor/ifdef.html
Declaration and definitions are two different things. For your case, you are allocating space for your structure in main.cpp. In your header, you should use the extern modifier for your struct so that all files that include the header file will look in the global namespace for the structure. Hope it helps.
The standard C/C++ approach:
// source.h
Put all struct, class, typedef, macro definitions, extern variable declaraltions
// source.cpp
Implement the class, functions, define global/external variables
// main.cpp, and other parts of program
#include"source.h"
You should define structure in the header file only, you should remove definition from main.cpp
May be you can give more information about what is the layout of your project.
Going by the guess, probably your problem can be either of the two:
you want forward declaration of struct.
using include guards to prevent redefinition.
See the following link for how to handle both:
http://www.adp-gmbh.ch/cpp/forward_decl.html
The header files also use include guards, so you can figure out what exactly can solve your problem.
If you want to share any variable between multiple cpp files, you should declare it in header as extern. And without extern in one of that c++ files.
If you don't do it, it'll lack at linking, because multiple objects would have variable with same name. Instead when using extern one object would have this variable and other objects link it.
The header is where you declare what your struct will consist of (probably a common.h file included by main.cpp and myfile.cpp):
struct MyStruct {
int messageID;
int tempVariable;
};
In your main.cpp, this is where you actually use the struct:
void someFunction() {
struct MyStruct tempStruct;
// do something with it
tempStruct.messageID = 1;
}
Don't put the definition of your struct in both your main.h and main.cpp - or you will get a redefinition error!
Also, don't include the cpp file - include the header file (e.g. common.h). Without knowing more about the structure of your program, it is hard to provide better information.