6

I'm writing little student project and stuck with the problem that I have a few global variables and need to use it in a few source files, but I get the error undefined reference to variable_name. Let's create three source files for example:

tst1.h:

extern int global_a;
void Init();

tst1.cpp:

#include "tst1.h"
void Init(){
  global_a = 1;
}

tst2.cpp:

#include "tst1.h"
int main(){
  Init();
}

When I compile and link, that's what I get:

$ g++ -c tst1.cpp 
$ g++ -c tst2.cpp 
$ g++ tst2.o tst1.o
tst1.o: In function `Init()':
tst1.cpp:(.text+0x6): undefined reference to `global_a'
collect2: error: ld returned 1 exit status

If I remove the extern statement, then I get the other problem, let me show:

$ g++ -c tst1.cpp 
$ g++ -c tst2.cpp 
$ g++ tst2.o tst1.o
tst1.o:(.bss+0x0): multiple definition of `global_a'
tst2.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

I really need some variables to be global, for example my little project works with assembly code, and have a variables like string rax = "%rax %eax %ax %ah %al"; which should be referenced through different source files.

So, how to properly initialize the global variables?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Hi-Angel
  • 4,933
  • 8
  • 63
  • 86
  • 2
    The best solution for this is to not use globals. For a hint on how you can avoid them: dependency injection. – Tim Seguine Dec 23 '13 at 19:17
  • @Tim, I know, that global variables is bad style, but in some situations it is the right way. For example if my project works with assembly, then many files shall know the names of CPU registers, and the variable `string rax = "%rax %eax %ax %ah %al";` should be referenced through different source files. – Hi-Angel Dec 23 '13 at 19:27
  • In general, static class members should be preferred for this. – leemes Dec 23 '13 at 19:35

3 Answers3

6

You only declared the variable but not defined it. This record

extern int global_a;

is a declaration not a definition. To define it you could in any module to write

int global_a;

Or it would be better to define function init the following way

int Init { /* some code */; return 1; }

and in main module before function main to write

int global_a = Init();
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

tst1.cpp should read instead:

#include "tst1.h"

int global_a = 1;

void Init(){  
}

You can also write the initializer line as:

int global_a(1);

Or in C++11:

int global_a{1};

A global should only be defined (i.e. written without the extern prefix) in one source file, and not in a header file.

Mike DeSimone
  • 41,631
  • 10
  • 72
  • 96
  • No, that's what I get: `tst1.cpp:2:5: error: redefinition of ‘int global_a’ int global_a = 33; ^ In file included from tst1.cpp:1:0: tst1.h:1:5: error: ‘int global_a’ previously declared here int global_a; ^` – Hi-Angel Dec 23 '13 at 19:21
  • Sorry, for the formatting. Shortly it says `tst1.cpp:2:5: error: redefinition of ‘int global_a’` – Hi-Angel Dec 23 '13 at 19:23
  • I was assuming your `tst1.h` had `extern int global_a;`, **as you wrote in the question,** not just `int global_a;`. – Mike DeSimone Dec 23 '13 at 20:13
  • that's right, but there was two right answer in the same time. I choose one, which autor brought me to the answer. Sorry, there is no way to choose two right answer, although I wanted and tried. – Hi-Angel Dec 23 '13 at 22:48
  • That's fine. It's just annoying when the code someone posts and the code they're trying to build aren't the same. – Mike DeSimone Dec 23 '13 at 23:08
0

you need to to add

#ifndef TST1_H
#define TST1_H
.....
#endif 

to tst1.h. it included twice in tst2.cpp

Mike Minaev
  • 1,912
  • 4
  • 23
  • 33
  • 1
    No, it's not included twice, it's compiled twice (in different translation units). An include guard doesn't solve this. – leemes Dec 23 '13 at 19:35