Global variables and scope - C++ - c++

I am having small problem in making a global variable works. I am using Visual Studio 2008 and standard C++.
I have two projects, one is a static library and second one is a test program which uses this library. I have a global variable in global.h like
#ifndef GLOBAL_H
#define GLOBAL_H
#include <string>
extern std::string globalWord;
#endif // GLOBAL_H!
I have a global.cpp where I am initializing this variable. This variable is used inside my library project. I am setting a value to this variable from the test project, but that value is not getting reflected in the library project.
I have debugged and it shows the new value in test project, but when the control reaches the library project, this variable value shows empty. So is this global variable's scope only limited to the project where it belongs to?
Or is there a better way to do this? I don't want to modify my function or constructor parameters in my library to pass this value.
Any help would be great.
Edit:
Here is how this variable is declared in global.cpp
#include <string>
#include "../global.h"
std::string globalWord = "";
This is how I used it in my library
#include "../global.h"
string text = globalWord;
Thanks

Don't use global variables. Just don't. Much better, if you HAVE to have globally accessible data, is to use a global function which will return globalWord, like this:
std::string globalWord()
{
static std::string word("Hi Mom");
return word;
}
This saves you from initialization order issues (read Effective C++ item #4).

With the "extern" keyword, you're telling the compiler that the actual variable exists somewhere else. You should also create a variable with the same name without the extern, in one and only one place. Ordinarily you'll get an error from the linker if you define two of them, but if one's in the library and one's not it might not figure it out.
Edit: make sure global.cpp is only in the library or test program, not both.

The problem is likely to be one of initialization order. When the program is linked, there are 2 places where globalWord is used in initialization:
in the initialization of text ("string text = globalWord;")
the initialization of globalWord itself
Unfortunately, the C++ standard does not specify the order of initialization of globals that come from different modules. Something similar to Matt's answer of using a function or a simple class (a singleton, for example) to access the global value is the usual way of enforcing a particular initialization order.
The C++ FAQ talks about this a little - if you plan to modify globalWord in your program, the situation is made a little more complex than they discuss because they don't seem to address setting the value hidden behind the "construct on first use" function. Typically something like that would require something like a singleton class.

The kind of behavior you describe seems more like a problem when you have a DLL, but you are saying that your library is static, which looks weird.
Anyway, take care with global variables in multiple libraries, if you have a shared code library (DLL) you'll get a value for each part. Check out this question, can be useful.

Related

Create a global array of objects in C++

I'm working on a drum pad to learn C++ programming.
I'm using a class called DrumSensor which I need to create 5 times in an array.
I'm using a header file "settings.h" to store variables I'll use throughout my code.
settings.h
extern DrumSensor sensor[5];
settings.cpp
#include "settings.h"
DrumSensor sensor[5];
I've been experiencing a lot with this global object array, but I've never been able to compile it.
I tried to find references such as:
Creating Array of Objects c++
c++ global object
The problem is, no matter how I try to declare my "DrumSensors", I get the following error:
... multiple definition of ...
You can take a look at the code here:
https://github.com/woodencase01/DrumSensor
About the code in your question
The way you have shown it is correct. You declared it in a header (and therefore, by extension, in any source file including that header), and defined it once in a source file.
You must be accidentally linking settings.cpp twice, or accidentally including settings.cpp somewhere, or you accidentally wrote another definition for this array somewhere.
About the code you pointed us to
FWIW, in the GitHub project you linked to, you do not have a settings.cpp, just a settings.h with loads of objects defined in it (i.e. without extern). So the problem may simply be that the code you are building is not the same code that you've been talking about.

Linker removing static initialiser [duplicate]

I am working on a factory that will have types added to them, however, if the class is not explicitly instiated in the .exe that is exectured (compile-time), then the type is not added to the factory. This is due to the fact that the static call is some how not being made. Does anyone have any suggestions on how to fix this? Below is five very small files that I am putting into a lib, then an .exe will call this lib. If there is any suggestions on how I can get this to work, or maybe a better design pattern, please let me know. Here is basically what I am looking for
1) A factory that can take in types
2) Auto registration to go in the classes .cpp file, any and all registration code should go in the class .cpp (for the example below, RandomClass.cpp) and no other files.
BaseClass.h : http://codepad.org/zGRZvIZf
RandomClass.h : http://codepad.org/rqIZ1atp
RandomClass.cpp : http://codepad.org/WqnQDWQd
TemplateFactory.h : http://codepad.org/94YfusgC
TemplateFactory.cpp : http://codepad.org/Hc2tSfzZ
When you are linking with a static library, you are in fact extracting from it the object files which provide symbols which are currently used but not defined. In the pattern that you are using, there is probably no undefined symbols provided by the object file which contains the static variable which triggers registration.
Solutions:
use explicit registration
have somehow an undefined symbol provided by the compilation unit
use the linker arguments to add your static variables as a undefined symbols
something useful, but this is often not natural
a dummy one, well it is not natural if it is provided by the main program, as a linker argument it main be easier than using the mangled name of the static variable
use a linker argument stating that all the objects of a library have to be included
dynamic libraries are fully imported, thus don't have that problem
As a general rule of thumb, an application do not include static or global variables from a library unless they are implicitly or explicitly used by the application.
There are hundred different ways this can be refactored. One method could be to place the static variable inside function, and make sure the function is called.
To expand on one of #AProgrammer's excellent suggestions, here is a portable way to guarantee the calling program will reference at least one symbol from the library.
In the library code declare a global function that returns an int.
int make_sure_compilation_unit_referenced() { return 0; }
Then in the header for the library declare a static variable that is initialized by calling the global function:
extern int make_sure_compilation_unit_referenced();
static int never_actually_used = make_sure_compilation_unit_referenced();
Every compilation unit that includes the header will have a static variable that needs to be initialized by calling a (useless) function in the library.
This is made a little cleaner if your library has its own namespace encapsulating both of the definitions, then there's less chance of name collisions between the bogus function in your library with other libraries, or of the static variable with other variables in the compilation unit(s) that include the header.

C++: What is the proper way to define non-class static const values?

First I'll try to describe the current situation:
I am adapting an existing code base for our uses and in some instances a .h/.cpp file contains multiple class definitions. We cannot change the existing public interface of the API without major modifications to other portions of the code that we would rather avoid at this time.
I have found the need for constant values that are used by more than one class (in the same .cpp file and nowhere else) and therefore cannot be defined as a class-specific constant. The only way I know to do this is to define the constants externally from any class (but still in the .cpp file) and reference them as needed.
I have done this and the code compiles and links, but when I go to run a test program on the code it fails with an error that appears to be related to the constant value I have defined. I get the impression that when the code executes, the constant has not actually been defined and the code blows up because of that.
I don't have a lot of experience writing C++ code and wonder if I'm doing this the wrong way. I will include code snippets below to try to illustrate what I'm doing.
In DateTime.cpp (currently nothing defined in DateTime.h for DATE_FORMAT_REGEX):
...
#include <boost/regex.hpp>
static const boost::regex DATE_FORMAT_REGEX("[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])(Z|([+|-]([01][0-9]|2[0-4]):[0-5][0-9]))?");
// Other class method implementations ...
bool our_ns::Date::parse_string(const std::string& s)
{
// Validate string against regex.
bool valid = boost::regex_match(s, DATE_FORMAT_REGEX);
if (valid) {
...
}
}
...
The call to regex_match is what fails. All of the classes, by the way are defined within a namespace in the header file.
It would appear the constant is not being initialized. What do I need to do to initialize these values? Based upon what I've described, is there a better way to do this?
[Update: 6/9/15 12:52 EDT]
Actually, I am relaying information witnessed by another developer in the organization. He verified in a debugger that the regex item was null when he reached the line where it blows up. He also mentioned that when he did some experimentation and moved the definitions from the .cpp to the .h file, the error did not recur. Beyond that, I don't know if things were executing properly.
The correct way is to not defined these as static const but rather as const. These are constants, they do not need static linkage. If you're doing it to avoid the global namespace, const variables have implicit compilation unit scoping anyway.
If Date::parse_string is called from a Date constructor and the Date object is static and initialized in a different compilation unit (C++ file) then it could be an issue related to static variable initialization order. In this case the order of initialization of variables is not defined so the Date object might be initialized before DATE_FORMAT_REGEX and as a result parse_string is called before DATE_FORMAT_REGEX is initialized. You can fix it by moving DATE_FORMAT_REGEX to the Date class definition.
This is likely a result of initialization order, a well-known issue that one could run into.
It has been described in books, such as C++ FAQs in detail for a very long time. Here is a quick reference:
https://isocpp.org/wiki/faq/ctors#static-init-order
Basically, there is no guaranteed order in which static variables must initialize. This creates situations where you could run into an error, when the "second" object makes use of the "first", but, "first" hasn't been initialized. Please note that "first" and "second" are interchangeable, therein lies the crux of the problem.
In fact, the more dangerous situation is a latent bug, where things continue to work until one day when they don't - usually, induced by a new compiler version or some such change.
It is better to get out of this dependency altogether. You don't seem to need to static here. If the goal is to limit visibility of the variable, then use anonymous namespace and place it before any use.

How to use global variables across projects in a solution?

I have a C++ solution in which there is a global variable which I want to be accessible across projects in the solution file. I know this is not recommended but what is the best way to do this?
Define the variable once, in the file that originally has the global variable and declare the variable extern in every file that uses it.
File 1:
int GlobalVariable;
int main(int argc, char *argv[]) {
// blablabla
}
File 2:
extern int GlobalVariable;
int somefunc(void) {
// blablabla
}
File 3:
extern int GlobalVariable;
// blablabla
All projects in a solution - ie you're building several dlls, grouped togetehr in a solution?
If that's the case then you have the problem that the a global in one dll cannot easily be read by another dll. You will need write the global to shared memory and have all dlls read from there.
An alternative aproach is easy: create a dll jsut to hold your shared variables and wrap them in a pragma. eg from this link:
#pragma data_seg (".myseg")
int i = 0;
char a[32]n = "hello world";
#pragma data_seg()
then each of your different dlls can link with the 'data dll', the data dll will contain a single instance of the variables no matter how many times its loaded or in which process. Performance counters use this technique to quickly pass data counters between the process that generates the data and perfmon.exe that reads and displays it.
There is a difference between Translation Unit and Project (specifically in Visual Studio).
In C and C++ you can make a global variable only accessible from the file in which it's declared by using the static keyword in front of the declaration. Globals that don't use the static keyword are accessible from any C or C++ file compiled into the program.
But frankly your question is not clear. When you say Global there can be lots of perspectives to it, as Wikipedia says in the article on Global Variables:
The C language does not use the term global, though in a small program contained in a single file it is possible to get the same effect by declaring a variable outside all functions (see below). However, such a variable should be called external, not global, since its scope is limited to the single file.
But, you may go through these links to see if you can solve the your specific problem:
Global variables/functions across different projects
Shared global variable in C++ static library
How to implement process-global variable in C++

Static variable initialization over a library

I am working on a factory that will have types added to them, however, if the class is not explicitly instiated in the .exe that is exectured (compile-time), then the type is not added to the factory. This is due to the fact that the static call is some how not being made. Does anyone have any suggestions on how to fix this? Below is five very small files that I am putting into a lib, then an .exe will call this lib. If there is any suggestions on how I can get this to work, or maybe a better design pattern, please let me know. Here is basically what I am looking for
1) A factory that can take in types
2) Auto registration to go in the classes .cpp file, any and all registration code should go in the class .cpp (for the example below, RandomClass.cpp) and no other files.
BaseClass.h : http://codepad.org/zGRZvIZf
RandomClass.h : http://codepad.org/rqIZ1atp
RandomClass.cpp : http://codepad.org/WqnQDWQd
TemplateFactory.h : http://codepad.org/94YfusgC
TemplateFactory.cpp : http://codepad.org/Hc2tSfzZ
When you are linking with a static library, you are in fact extracting from it the object files which provide symbols which are currently used but not defined. In the pattern that you are using, there is probably no undefined symbols provided by the object file which contains the static variable which triggers registration.
Solutions:
use explicit registration
have somehow an undefined symbol provided by the compilation unit
use the linker arguments to add your static variables as a undefined symbols
something useful, but this is often not natural
a dummy one, well it is not natural if it is provided by the main program, as a linker argument it main be easier than using the mangled name of the static variable
use a linker argument stating that all the objects of a library have to be included
dynamic libraries are fully imported, thus don't have that problem
As a general rule of thumb, an application do not include static or global variables from a library unless they are implicitly or explicitly used by the application.
There are hundred different ways this can be refactored. One method could be to place the static variable inside function, and make sure the function is called.
To expand on one of #AProgrammer's excellent suggestions, here is a portable way to guarantee the calling program will reference at least one symbol from the library.
In the library code declare a global function that returns an int.
int make_sure_compilation_unit_referenced() { return 0; }
Then in the header for the library declare a static variable that is initialized by calling the global function:
extern int make_sure_compilation_unit_referenced();
static int never_actually_used = make_sure_compilation_unit_referenced();
Every compilation unit that includes the header will have a static variable that needs to be initialized by calling a (useless) function in the library.
This is made a little cleaner if your library has its own namespace encapsulating both of the definitions, then there's less chance of name collisions between the bogus function in your library with other libraries, or of the static variable with other variables in the compilation unit(s) that include the header.