0

I’ve used global variables without having any noticeable problems but would like to know if there are potential problems or drawbacks with my use of globals.

In the first scenario, I include const globals into a globals.h file, I then include the header into various implementation files where I need access to any one of the globals:

globals.h
const int MAX_URL_LEN = 100;
const int MAX_EMAIL_LEN = 50;
…

In the second scenario, I declare and initialize the globals in an implementation file when the application executes. These globals are never modified again. When I need access to these globals from a different implementation file, I use the extern keyword:

main.cpp
char application_path[128];
char data_path[128];
// assign data to globals
strcpy(application_path,  get_dll_path().c_str());
…

do_something.cpp
extern char application _path[]; // global is now accessible in do_something.cpp

Regarding the first scenario above, I’ve considered removing all of the different “include globals.h” and using extern where access to those globals is needed but have not done so since just including the globals.h is so convenient.

I am concerned that I will have different versions of the variables for each implementation file that includes globals.h.

Should I use extern instead of including the globals.h everywhere access is needed?

Please advise, and thank you.

Caroline Beltran
  • 888
  • 2
  • 9
  • 22
  • 1
    Advice: constants are fine, but don't use global variables. Pass data or objects as needed. – crashmstr Mar 09 '15 at 18:29
  • You might want to take a look at this regarding global variables as a whole: http://stackoverflow.com/questions/484635/are-global-variables-bad – NathanOliver Mar 09 '15 at 18:30
  • You can put `extern something;` in a header and then include that header insted of writing externs manually. Also, you shall not use names starting with `_` at global namespace (because standard says so). – HolyBlackCat Mar 09 '15 at 18:32
  • 1
    I would strongly advise creating functions that provide access to the global data, such as `extern char const* get_application_path();` instead of providing direct access to the data. – R Sahu Mar 09 '15 at 18:35

3 Answers3

3

Your implementation is fine for now. Globals become a problem when

  1. Your program grows and so does your number of globals.
  2. New people join the team that don't know what you were thinking.

Number 1 becomes particularly troublesome when your program becomes multi-threaded. Then you have a number of threads using the same data and you may require protection, which is difficult with just a list of globals. By grouping data in separate files according to some criteria such as purpose or subject matter your code becomes more maintainable as it grows and you leave breadcrumbs for new programmers on the project to figure out how the software works.

Bruce
  • 2,230
  • 18
  • 34
  • Re "Your implementation is fine for now", absolutely not. Exposing logical constants as mutable global variables is very ungood. – Cheers and hth. - Alf Mar 09 '15 at 18:58
  • Alf: Your point is well-taken, but sometimes quick and dirty is perfect for what you're trying to accomplish, especially if you don't know any better. – Bruce Mar 09 '15 at 19:05
  • @LightnessRacesinOrbit: I never respond to comments. – Bruce Mar 09 '15 at 20:26
3

Global mutable variables

  • provide invisible lines of influence across all of the code, and
  • you cannot rely on their values, or whether they've been initialized.

That is, global mutable variables do for data flow what the global goto once did for execution flow, creating a spaghetti mess, wasting everyone's time.

Constant global variables are more OK, but even for those you run into

  • the initialization order fiasco.

I remember how angry I got when I realized that all my troubles in wrapping a well known GUI framework, was due to it needlessly using global variables and provoking the initialization order fiasco. First the anger was directed at the author, then at myself for being so stupid, not realizing what was going on (or rather, was not going on). Anyway.

A sensible solution to all this is Meyers' singletons, like

inline
auto pi_decimal_digits()
    -> const string&
{
    static const string the_value = compute_pi_digits();
    return the_value;
}

For the case of a global that's dynamically initialized from some place that knows the value, “one programmer's constant is another programmer's variable”, there is no good solution, but one practical solution is to accept the possibility of a run time error and at least detect it:

namespace detail {
    inline
    auto mutable_pi_digits()
        -> string&
    {
        static string the_value;
        return the_value;
    }
}  // namespace detail

inline
void set_pi_digits( const string& value )
{
    string& digits = detail::mutable_pi_digits();
    assert( digits.length() == 0 );
    digits = value;
}

inline
auto pi_digits()
    -> const string&
{ return detail::mutable_pi_digits(); }
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • What do you mean by "the global `goto`"? What's "global" about it? – Lightness Races in Orbit Mar 09 '15 at 19:19
  • @LightnessRacesinOrbit: C and C++ lack a global `goto`, unless you count `longjmp`. – Cheers and hth. - Alf Mar 09 '15 at 19:48
  • Yes, I know; that's why I asked you why you mentioned a hypothetical "global `goto`" in a C++ answer. – Lightness Races in Orbit Mar 09 '15 at 20:04
  • @LightnessRacesinOrbit: Oh. I referred to history. Specifically, a guy called Edsger Dijkstra once wrote an article, now famous, called "GOTO considered harmful". I think it's available from the ACM as a classic. This article paved the way for what was then known as *structured programming*, using control flow constructs such as `while` and `if`. But the problems Dijkstra discussed were not the kind that would be caused by a C or C++ local `goto`, at least not in ordinary small functions. These problems were caused by (very real) unrestricted global `goto` features. – Cheers and hth. - Alf Mar 09 '15 at 20:19
  • You should read "'GOTO considered harmful' considered harmful", published in 1987. It's an eye-opener. – Lightness Races in Orbit Mar 10 '15 at 00:52
  • @LightnessRacesinOrbit: Thanks! Will do. I may have read it but I don't exactly remember it. – Cheers and hth. - Alf Mar 10 '15 at 01:03
  • @LightnessRacesinOrbit: haven't found the letter (by Frank Rubin) yet, but I found Dijkstra's rejoinder: https://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EWD1009.html – Cheers and hth. - Alf Mar 10 '15 at 03:49
  • @LightnessRacesinOrbit: Found it, at (http://web.archive.org/web/20090320002214/http://www.ecn.purdue.edu/ParaMount/papers/rubin87goto.pdf), it is indeed interesting. Frank makes an argument in favor of `goto` based on Pascal's lack of a `continue` statement. Possibly the most common ways that Frank put `goto` to work in Pascal-like code are covered by more safe C++ statements like `break`, `continue`, `return` and `throw`, but still there might be cases where a well-placed `goto` might simplify things greatly. – Cheers and hth. - Alf Mar 10 '15 at 03:58
  • I still typically use it for FSAs. – Lightness Races in Orbit Mar 10 '15 at 09:43
1

One issue with globals is that when you go to include 3rd party libraries in your code, sometimes they've used globals with the same names as yours. There are definitely times when a global makes sense, but if possible you should also take care to do something like put it into a namespace.

RyanP
  • 1,898
  • 15
  • 20