unresolved extern symbols - trying global for all files

Pages: 12
I need a little help with this one. I have already searched the net and have tried all the suggestions posted, but still I am having issues.

My goal is to have global variables/constants available to all files. Whatever I try I either get "unresolved external symbol", "undefined symbol" or "already defined in ____". I feel that I am running in circles!

The following is code that I am experimenting with in order to fix the issue.
You may need to substitute the print statement part and remove the space name AGK.

Also, this isn't just for an array. The issue happens with all the varibles declared in constants.h

template.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  // Includes
#include "constants.h"
#include "quarks.cpp"

// Namespace
using namespace AGK;


app App;

void app::Begin(void)
{
	
}

void app::Loop (void)
{
	

	TEST();
}


void app::End (void)
{

}


constants.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>

#ifndef globals_H_
#define globals_H_ 

struct _timer
{
	int Active;
	float Start;
	float Delay;
	float Duration;
	float Elapse;
};

extern _timer TOOK[8];

#endif 


quarks.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "template.h"
#include "constants.h"
#include <string>

using namespace AGK;
using namespace std;

#ifndef quarks_
#define quarks_

int TEST()
{
	agk::Print(TOOK[0].Delay);
	agk::Sync(); ;
	return 0;
}

#endif 


CONSTANTS.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "constants.h"

int CONSTANTS()
{	
	//in minutes
	TOOK[0].Delay = 30.0;
	TOOK[0].Duration = 0.0;
	TOOK[1].Delay = 30.0;
	TOOK[1].Duration = 10;
	TOOK[2].Delay = 40;
	TOOK[2].Duration = 480;
	TOOK[3].Delay = 20;
	TOOK[3].Duration = 720;
	TOOK[4].Delay = 60;
	TOOK[4].Duration = 480;
	TOOK[5].Delay = 10;
	TOOK[5].Duration = 180;
	TOOK[6].Delay = 60;
	TOOK[6].Duration = 420;
	TOOK[7].Delay = 10;
	TOOK[7].Duration = 240;

	return 0;
}


Thanks in advance.
The minimum change to your code to resolve the problem is to change constants.cpp. Just add the following line before 'int CONSTANTS()':

_timer TOOK[8];
> #include "quarks.cpp"
No, don't include cpp files.

http://www.cplusplus.com/forum/general/113904/ (undefined reference)
http://www.cplusplus.com/forum/general/140198/ (multiple definitions)
you need to have _timer TOOK[8]; in one source file.

> Whatever I try I either get "unresolved external symbol", "undefined symbol" or "already defined in ____".
Post the exact error message and your build command.


> My goal is to have global variables/constants available to all files.
¿are you sure that you need that?
Last edited on
constants.h says that TOOK[] exists somewhere, but it does not.
constants.cpp tries to initialize an array named TOOK[] that does not exist.

I am not sure why you have a function named CONSTANTS.

constants.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "constants.h"

_timer TOOK[8] =
{
  { 0, 0, 30,   0, 0 },
  { 0, 0, 30,  10, 0 },
  { 0, 0, 40, 480, 0 },
  { 0, 0, 20, 720, 0 },
  { 0, 0, 60, 480, 0 },
  { 0, 0, 10, 180, 0 },
  { 0, 0, 60, 420, 0 },
  { 0, 0, 10, 240, 0 }
};

You should be aware that it is not safe to name global variables with leading underscore(s). Especially something like the word "timer", which is almost guaranteed to have a collision with something in libc.

Also, I'm a bit confused why "constants.h" has an include guard named "globals_H_".

Hope this helps.
"No, don't include cpp files."
If I do not include the .cpp file I get "undefined reference)

"Post the exact error message and your build command."
If you try running the code you would see the error. I am using whatever Microsoft does when I press "Build".

"¿are you sure that you need that?"
Yes.

"I'm a bit confused why "constants.h" has an include guard named "globals_H_""
I get redefined errors if the guard does not exist.

"The minimum change to your code to resolve the problem is to change constants.cpp. Just add the following line before 'int CONSTANTS()':"
Tried that, made no difference.

"I am not sure why you have a function named CONSTANTS."
I am assigning values to several cells of several arrays and using a function saves space. There are thousands of more lines of code in my original written in AGK basic, which works just fine.


So, no one yet knows how to have global variables av ailable to all files?







Last edited on
initialize your array at the beggining of the cpp file, not in a function even if it is legal. why? do you ever call this function , no, so your data is not initialized properly.

no include cpp files, why? the compiler might look several at your header but the linker only create once your obj file from your cpp, you will get errors for sure.

you need to think like a compiler and know where do I need to include this or that.


remove the extern variable from the inclusive guard it must stay in a global scope

from template.cpp remove quark.cpp put .h instead and declare extern Test(); then in quarks.cpp you include quark.h , also remov the ifnde you wont need it it an extern.

your object App put it in main , also it makes no sense the class is app and the instance is App. start class name always with a capital.

just for recall , header -> declare , cpp -> implement , anywhere you need something from a file, always include the header. #ifndef in headers. using namespace in cpp only

if you need more detail let us know.
So, no one yet knows how to have global variables available to all files?

We all know how to do it.

You are rejecting our advice and claiming that we are ignorant.

We all know how to make it work. You are the one who does not.


"No, don't include cpp files."
If I do not include the .cpp file I get "undefined reference)

You get an undefined reference because quarks.cpp does not have an appropriate quarks.h file that describes the stuff found in quarks.cpp. Every .cpp should have an associated .h file.
http://www.cplusplus.com/faq/compiling/files/#headers

"Post the exact error message and your build command."
If you try running the code you would see the error. I am using whatever Microsoft does when I press "Build".

That's a cop-out response. No one magically knows what your compile environment is, nor can any one solve unknown errors for you. I could tell you exactly how to make it compile with the GCC, but that would be of no use to you.

What has been asked of you is simply that your provide us with enough information to diagnose your specific problems so that we can help you recognize and repair them.

"I'm a bit confused why "constants.h" has an include guard named "globals_H_""
I get redefined errors if the guard does not exist.

I didn't ask why you are using an include guard. I asked why you have named it something different than the name of your module. While not law, a very good recommendation is that you name your include guards the same as your include file, including all path information.

Anything I personally create will have include guards of the form
    DUTHOMHAS_ [path] _ module_name _HPP  

Hence, if I create an include file (quuxer.hpp) for quuxer.cpp, it will have an include guard of the form:
#ifndef DUTHOMHAS_QUUXER_HPP
It will not be:
#ifndef DUTHOMAHS_FOOZLE_HPP

"The minimum change to your code to resolve the problem is to change constants.cpp. Just add the following line before 'int CONSTANTS()':"
Tried that, made no difference.

Then you are doing something more wrong than you have let us know. I can take your sources and compile them with that change.

"I am not sure why you have a function named CONSTANTS."
I am assigning values to several cells of several arrays and using a function saves space. There are thousands of more lines of code in my original written in AGK basic, which works just fine.

And yet you are having difficulty with it now.

The point isn't to incite ire and snark from you, but to point out that you have a design flaw.


So, no one yet knows how to have global variables available to all files?

Yes, and you've been told twice how to fix it.

constants.cpp
 
_timer TOOK[8];

Good luck.
Avoid user-defined identifiers starting with an underscore (like _timer) at global namespace scope.

... some identifiers are reserved for use by C ++ implementations and shall not be used otherwise;
no diagnostic is required.

Each identifier that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.

Each identifier that begins with an underscore is reserved to the implementation for use as a name in the global namespace. - IS
@Duoas (9940)

I am not sure where you are getting that I am exhibiting a bad attitude. What ire and snark? You are reading too much into it.

Yes, I have tried all suggestions up to Oct 23. Nothing has worked so far. The code you see posted by me is the result of "help". So I came to this forum to see if the help would be different (better).

I already mentioned the errors. There is no cop out. If different compilers report differently enough to where my discription isn't adequate, I apologize, I have not used but two different compilers since the '80's, nor have I written in C since.

I will try the further suggestions and see what happens.

Thanks for the responses.
> I already mentioned the errors.
You've provided incomplete information
Whatever I try I either get "unresolved external symbol", "undefined symbol" or "already defined in ____".
¿what symbols were undefined/unresolved?
¿what symbols were already defined? ¿where?
¿what have you tried? (your build command)


As for your errors
- you are including a *.cpp. That gives you "multiple definitions"
- you fail to define the variable. That gives you "undefined reference"
- your project may be misconfigured. That may give you "undefined reference" and "multiple definitions"


If I do not include the .cpp file I get "undefined reference)
weird, you should get a `was not declared' error, `template.cpp' would not compile and you wouldn't reach the linking stage.
Just taking a stab here... This looks over my head, but I noticed you have

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

app App;

void app::Begin(void)
{
	
}

void app::Loop (void)
{
	

	TEST();
}


void app::End (void)
{

}


You have app App; like you are making an instance of a class. Shouldn't your function calls be App::Begin(void) instead of app::Begin(void) and so on? Calling them with the object and not the class?
closed account (48T7M4Gy)
use
Last edited on
This is what happens without including the .cpp file:

template.cpp(21): error C3861: 'TEST': identifier not found

If I include the .cpp file the error goes away. Perhaps this is the reason to have a 'quarks.h' file?
closed account (48T7M4Gy)
T
Last edited on
It appears that using header files for the .cpp files has rid me of errors.

Now to see if the global part of the global variable is actually working...

Yep, seems to be working. I ran the executable and the expected result printed to screen.

Now for mega hours of modifying the actual game code!!

Thanks all. It has been a while since I learned C in school, but that was before they added any plus signs. :)
Last edited on
AND I did get rid of the 'extern'. Other forums told me I needed to use that for multiple file globals. Obviously, it is not necessary.

Last edited on
closed account (48T7M4Gy)
[
Last edited on
Twas but an illusion... still getting the same errors when other variables are added.

Once I define/declare a function in a .cpp, I shouldn't have to define it again when calling from another .cpp, correct? Or does the prototype for the function need to be in the header of the calling .cpp?

I keep getting toggling errors. Fix one error, a different one appears. Fix that one, and I get the original error. Now, the functions are having "symbol undefined" errors, but 'fixing' that gets me back to "already defined" errors.

I will get back later after I study the issue by using my above example code. I will add one variable at a time until I see the pattern.
> Once I define/declare a function in a .cpp, I shouldn't have to define it again when calling from another .cpp, correct?

Right.
Once I define a (non-inline) function (with external linkage) in a translation unit, I shouldn't define it again in any other translation unit.


> Or does the prototype for the function need to be in the header of the calling .cpp?
Yes. A declaration of the function must be available before it can be used.

1
2
3
4
5
6
7
8
9
10
11
12
/////////////// header a.h //////////////////////

// include guard. see: https://en.wikipedia.org/wiki/Include_guard
#ifndef A_H_INCLUDED
#define A_H_INCLUDED

int my_function( int arg ) ; // declare the function in the header

extern int my_variable ; // declare the variable in the header


#endif // A_H_INCLUDED 


1
2
3
4
5
6
7
8
9
10
11
/////////////// implementation a.cpp //////////////////////

#include "a.h" // include its header right at the top, before any other #include
#include <cmath>

int my_function( int arg ) // define the function in the implementation file
{
    return arg * ++my_variable ;
}

int my_variable  = 1 ; // define the variable in the implementation file 



1
2
3
4
5
6
7
8
9
10
11
/////////////// another implementation file (say main.cpp) //////////////////////

#include <iostream> // this declares std::cout
#include "a.h" // this declares my_function and my_variable

int main() // use my_function and my_variable
{
    my_variable = 72 ;

    std::cout << my_variable << ' ' << my_function(23) << '\n' ;
}
I have know idea what is going on.

I get errors for certain variables, arrays or structs. I copy and paste those very same variables and associated code into my test code (based on my first post) and all those variables, arrays and structs work just fine!!

I am doing a copy and paste so everything is exactly the same, except not as many variables.

I am beginning to think there is something wrong with Visual Studio...

So far, the observation is that low number of variables works, larger number of variables is causing the errors that I have been seeing (redefined symbols, undefined symbols, unresolved external symbol). All those errors happen starting with the exact same project template I am using without errors in the smaller test code.

Could it be that there are so many errors that the compiler is getting confused??
Last edited on
Pages: 12