How to properly initialize global variables? [duplicate] - c++

This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 9 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
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?

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();

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.

you need to to add
#ifndef TST1_H
#define TST1_H
.....
#endif
to tst1.h. it included twice in tst2.cpp

Related

Why const objects are local to file in c++? [duplicate]

This question already has answers here:
Why does "extern const int n;" not work as expected?
(5 answers)
Closed 4 years ago.
Consider the following a.cpp and b.cpp files:
ebra#him:/tmp$ cat a.cpp
const int i = 5;
ebra#him:/tmp$ cat b.cpp
int main()
{
extern int i;
return i;
}
ebra#him:/tmp$ g++ *.cpp
/tmp/ccqBWi4e.o: In function `main':
b.cpp:(.text+0x6): undefined reference to `i'
collect2: error: ld returned 1 exit status
The question is how I can use the i variable that is declared in a.cpp file inside b.cpp?
Note that
I added the keyword const inside b.cpp too, but nothing changed.
I have the same problem with static and static const variables too!
In C++, when you declare a variable to be const at namespace scope it automatically has internal linkage. Adding static will also yield in internal linkage with or without const
Therefore they are not available outside the translation unit, hence the linker error.
Put it in a header file, that way they both have the same value (different variables, same name, same value).
I think you can also override to make it external linkage, but this will get you nothing: no behaviour changes; No efficiency improvement, for int.

C++ Class Method contains Undefined Reference to a Static Variable

In C++, I'm trying to implement an enum to be accepted as a parameter in a method and consistently receive linking errors (undefined reference). Let me provide my header, implementation, and sample main execution. Also note that I am using a Makefile and can provide that if you believe the issue to be within the Makefile.
Header:
// Make sure definitions are only made once
//
#ifndef MYTEST_H
#define MYTEST_H
// System include files
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// Declare class definitions
//
class MyTest {
// Public data
//
public:
// Define debug_level choices
//
enum DBGL {FULL = 0, PARTIAL, BRIEF, NONE};
// Define a debug_level variable
//
static DBGL debug_level_d;
// Define public method set_debug that sets debug level to a specific value
//
bool set_debug(DBGL x_a);
// End of include file
//
#endif
Here is my implementation file 'mytest_00.cc'. Here, I am attempting to define an enum type "DBGL" as the debug level. And then I am trying to accept that as a parameter in the method 'set_debug'.
#include "mytest.h"
// Implementations of methods in MyTest
// Declare debug_level
//
static MyTest::DBGL debug_level_d = MyTest::FULL;
// Implement set_debug method to set the debug_level_d
// FULL = 0, PARTIAL = 1, BRIEF = 2, NONE = 3
//
bool MyTest::set_debug(MyTest::DBGL x_a) {
// Set debug_level_d to the argument provided
//
debug_level_d = x_a;
// exit gracefully
//
return true;
}
The goal is to test the class 'mytest' in the main function by executing something like:
MyTest Test;
Test.set_debug(FULL);
And this code would set the variable 'debug_level_d' as the parameter passed.
The error I receive upon compilation is as follows:
g++ -O2 -c mytest.cc -o mytest.o
g++ -O2 -c mytest_00.cc -o mytest_00.o
g++ -g -lm mytest.o mytest_00.o -o mytest.exe
mytest_00.o: In function `MyTest::set_debug(MyTest::DBGL)':
mytest_00.cc:(.text+0x12): undefined reference to `MyTest::debug_level_d'
collect2: error: ld returned 1 exit status
make: *** [mytest.exe] Error 1
Any help in understanding why this error is occurring would be greatly appreciated. I've been stuck on this for a day now. Please let me know if any details require further clarification.
Thank you.
You should not use the static keyword when defining the field in the .cpp file, only when declaring it in the class. Note in the code comments you have "declaring" and "defining" the wrong way round.
Additionally, when defining the member, you need to qualify it with the class name.
So the .cpp definition should be:
MyTest::DBGL MyTest::debug_level_d = MyTest::FULL;
By using the static keyword in the definition, you restrict it to internal linkage.
See: http://en.cppreference.com/w/cpp/language/static

Separate header file and its logic in c++ [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 5 years ago.
Please make me understand how header files works in C++. I am using osx and g++ compiler. I have
main.cpp
#include<iostream>
#include "myfunc.hpp"
using namespace std;
int main() {
square(10);
return 0;
}
myfunc.hpp
#ifndef MYFUNC_HPP_
#define MYFUNC_HPP_
/*
void square(int x) {
std::cout << x * x << std::endl;
};
*/
void square(int);
#endif // MYFUNC_HPP_
myfunc.cpp
#include<iostream>
#include "myfunc.hpp"
using namespace std;
void square(int x) {
cout << x * x << endl;
}
Now when I am trying to compile using g++ main.cpp , its giving
Undefined symbols for architecture x86_64:
"square(int)", referenced from:
_main in main-088331.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Because it is not able to find the function definition of square that is defined in myfunc.cpp.
But, if I defined square function in header file, it works because now it finds the function definition.
I want to use the function defined in myfunc.cpp in main.cpp, so I am using the header file myfunc.hpp. How can I achieve this? Am I doing something wrong here? Maybe my concept is not that clear about headers since I am new to C++ programming.
When you call g++ main.cpp, the compiler will try to compile and link the program, yet for linking, it lacks the source- or object file containing the definition of square. So it could compile main.cpp based on the function prototype given in the header file, yet it cannot link then.
To just compile main.cpp write
g++ -c main.cpp
To compile and link the complete program write:
g++ main.cpp myfunc.cpp
For more details concerning programs comprising several translation units confer, for example, this link.

C++ compiler issue (?): can't pass arguments to functions in separate class files [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is an undefined reference/unresolved external symbol error and how do I fix it?
I recently started working on an interpreter in C++, but I got annoyed that vectors or arrays could not be passed to external class methods no matter what I tried and so I deleted everything I had worked on. As it turns out, I can't pass even an int to another class. I decided to give C++ another chance before resorting to C or Java, but the compiler still doesn't work as I would expect. Maybe I'm forgetting something simple about C++, as I haven't used it in a while, but this seems simple enough. My problem is: I can't pass arguments to methods in other classes when they're not defined in the same file. Here's what I'm trying to do:
Main: main.cpp
#include "myclass.h"
int main() {
MyClass test;
int n = test.add(25, 30);
return n;
}
Header: myclass.h
class MyClass {
public:
int add(int a, int b);
};
Class implementation: myclass.cpp
#include "myclass.h"
int MyClass::add(int a, int b) {
return a + b;
}
Compiling this with g++ main.cpp yields
/tmp/ccAZr6EY.o: In function main':
main.cpp:(.text+0x1a): undefined reference toMyClass::add(int, int)'
collect2: error: ld returned 1 exit status
What the heck am I doing wrong? Also, the compiler yells at me for the same thing even if my functions aren't parameterized, so it must be a problem with the header.
Any help is much appreciated - thanks!
You need to compile both files
g++ main.cpp myclass.cpp
If you only compile main.cpp, the compiler finds the declaration of MyClass::add in your header but the linker later fails to find an implementation of MyClass::add to jump to.

C++: Linking files with GCC compiler

I have three files : myh.h; my.cpp; use.cpp. Here are the contents of the files:
myh.h
extern int foo;
void print_foo();
void print(int);
my.cpp
#include "myh.h"
#include <iostream>
void print_foo()
{
std::cout<<foo<<std::endl;
}
void print(int i)
{
std::cout<<i<<std::endl;
}
use.cpp
#include "myh.h"
int main()
{
foo=7;
print_foo();
print(99);
return 0;
}
GCC spews out the following error:
my.o:my.cpp:(.text+0x7): undefined reference to `foo'
use.o:use.cpp:(.text+0x10): undefined reference to `foo'
collect2: ld returned 1 exit status
I compile the files using the -c command and it doesn't give errors. I link using the following command:
g++ -o final my.o use.o
What is the problem here, I read other topics with similar problems, and the case here is just strange .....
For the curious this is an exercise drill from Stroustrup's book Programming principles of using C++
Edit: I did as dasblinkenlight said, and in use.cpp I added an int in front of foo (so now foo is defined), but I still get this error:
my.o:my.cpp:(.text+0x7): undefined reference to `foo'
collect2: ld returned 1 exit status
Which tells me that it is not defined in my.cpp also? If I have to define it everywhere what is the point of including it in the header file, or how should this be approached more appropriately?
You get a linker error because you declared foo, but you never defined it.
extern int foo is only a declaration; it does not cause allocation of memory for the foo variable, only promises that you will do it at some other place. To fix it, you need to add this line to one of the cpp files, like this:
#include "myh.h"
int foo;
int main()
{
foo=7;
print_foo();
print(99);
return 0;
}
The problem is that foo is declared but not defined. You need to define foo in exactly one of the translation units, e.g.:
int foo = 0;