8

In general, I know that global variables are bad and should be avoided. Are static global variables equally bad?

In all my projects, I have heavily relied on static global variables. From design perspective, how can I avoid using them.

Ex Use case :

Whenever the key is changed(by some other threads), my call back notifier is executed in which I update my static global variable with the new key. This key is used everywhere in the program to decrypt some data.

How can I avoid static globals in this case?

Sandeep
  • 179
  • 1
  • 6
  • 1
    What peril(s) are you trying to avoid by eliminating the static, global variable? – Robert Harvey Apr 07 '16 at 02:12
  • 2
    The only difference between a `static` and a non-`static` global variable is that the former can only be accessed from within the translation unit it is defined in. This helps reduce name-space pollution and might improve performance but it doesn't make the other concerns about global variables disappear. – 5gon12eder Apr 07 '16 at 02:23
  • 1
    What are the other concerns? Any discussion about removing a global variable is pointless unless the cost/benefit ratio is understood. – Robert Harvey Apr 07 '16 at 02:25
  • 1
    @RobertHarvey I agree that a discussion about whether or not to remove global variables should start by identifying the problems associated with them. I also believe, however, that *if you come to the conclusion* that you want to remove global variables, simply making them `static` will not change much. They will still be global variables. – 5gon12eder Apr 07 '16 at 02:48
  • @5gon12eder Totally agree. I was designing a library in which i used a static global variable. Because of this I had to put a constraint that the application using this library should be accessing my library fundtions only from a single thread. I did not totally like this. What I am not sure is the ways how I can avoid them. I mentioned an example use case.. In that case, what is the alternate solution to avoid using static global variable? – Sandeep Apr 07 '16 at 03:37
  • @RobertHarvey please look at my above comment. – Sandeep Apr 07 '16 at 03:37
  • @manty: Try a threadsafe global. See http://stackoverflow.com/q/1338846/102937 – Robert Harvey Apr 07 '16 at 03:46
  • Is your question how to *avoid sharing* the same variable between threads (ie have each thread use its own private variable) or how to *make the sharing safe*? Anyway, if either of these is your main concern, you should probably re-word your question a little as it currently doesn't communicate this very clearly. – 5gon12eder Apr 07 '16 at 03:56
  • 2
    So, the key might be changed by another thread at any time? What happens if you are in the middle of using the key? – Winston Ewert Apr 07 '16 at 05:18
  • You could pass the key holder to as much code as possible. Or you could collect several global variables in a context struct and pass it to the code that needs it. – CodesInChaos Apr 07 '16 at 07:55

4 Answers4

9

Whenever the key is changed(by some other threads), my call back notifier is executed in which I update my static global variable with the new key. This key is used everywhere in the program to decrypt some data.

What is trapping you in this kind of thinking is the concept of "the key". It should be "a key".

You think of the key as global so anything that would hold it must be global. Imagine your requirements change and suddenly there are 5 keys running around.

Can't imagine that? Fine, imagine 5 systems, that do nearly the same thing, that must have different keys and all need to be part of your application. How much of your code could be reused?

The key belongs in a context. Within that context there will be only one key. But that doesn't mean there will only ever be one context.

Rather than force everything to find this key by knowing "the one true key" tell them what context they are in by passing them some way to find the key they care about.

That means the key will still only be stored in one place. But now only one place decides where that place is. If you make it global then everything has to know where it is and AGREE on where that is. Ick.

candied_orange
  • 102,279
  • 24
  • 197
  • 315
  • But, if the OP really *does* want every module in the application to use "the one true key" .. it *is* a global, even if it's not programmed like one. And, it'll be much more work and maintenance if the OP is creating and managing contexts to ultimately simulate a global... – svidgen Oct 21 '16 at 21:46
  • @svidgen you can tell every module to use the one true key in main. This way the decision that there is one true key happens in one true place. And you can do it in a way that I can pass them the one true bad key and be sure they don't give up Excalibur to just any British tyrant that asks for it. – candied_orange Oct 21 '16 at 23:32
4

A static global variable is the same global variable, just with a limited compile-time visibility, as @5gon12eder notices above.

Global static state is prone to race conditions. If you have multiple threads accessing this state, you might need locking. If you only have one thread allowed to change the value, you may still have race conditions unless other threads make a copy of the value once and don't depend on repeated reads of the global variable returning the same value.

If you are an expert at writing lock-handling code, you may be fine with that. But likely you won't be asking this question then.

If you have a single-threaded program, these problems mostly go away; the remaining problems may be in unaccounted-for interactions between functions via the global value.

This all is well-known, just summed it up for you.

9000
  • 24,162
  • 4
  • 51
  • 79
  • Thank you. I am well aware of the locking mechanisms. Also the concepts of single-multitheraded stuff. But I am not able to imagine a solution as a substitute for the static global variables.. i mentioned a use case. How can that be acieved without using static global variable? – Sandeep Apr 07 '16 at 03:33
  • @Manty: The typical solution (in C) to replace global variables is to allocate a structure and pass the pointer to it around everywhere. – Bart van Ingen Schenau Apr 07 '16 at 06:36
2

The biggest problem with a global variable is that it is global, so anyone can access and modify it at any time. That problem is immensely reduced with a static variable, because all code accessing and modifying the variable is in that one file, and hopefully under your control. (There is no such thing as a "static global" variable, that's self contradictory. You mean a static variable with the same life time as the application).

The second big problem with a global variable is that you may not need one, but two or more. Yes, that problem will remain the same. If your code is restricted by the fact that there is only one global variable, then you lose functionality, or your code may not be thread safe, and so on. That's a problem and needs to be handled for a static variable just as for a global variable.

Depending on the language, it can be the fact that it is a plain variable that causes you problems. Plain variables can usually be accessed without any precautions. If that is a problem, then you probably need some accessor functions. You'd have a static variable only accessible to an accessor. That doesn't help if the problem is just having global state, but it helps if the problem is uncontrolled access to that global state.

gnasher729
  • 42,090
  • 4
  • 59
  • 119
0

You are asking the right question: from a design perspective what can you do to avoid using global variables.

The big clue here is that you say that you rely heavily on global variables. This tells me that your designs are not modular enough. I have seen this before in nasty old embedded projects that have grown from small, easy to understand loops into ugly beasts.

A good modular design has many benefits including eliminating the use of these globals and making TDD much easier - unit testing is much easier. Your module may have it's own internal static data which is 'global' to the module, but nothing outside the module can access it. You will create access functions as needed so other parts of the program can do their work. This approach forces you to think carefully about what you are doing and to try and build modules that do specific work.

A side benefit of this approach is that you will start being able to reuse these modules in other projects since they have become more generic in function.

Tereus Scott
  • 296
  • 1
  • 4