2 min read

Wow, they were right, global variables are bad

Topics:

You hear it again and again from software developers. Global variables are evil. Global variables are bad. Global variables were the downfall of the Roman empire. I could sort of understand where the statements were coming from, but it didn't totally hit me until I started working on our Windows simulator.

In our runtime, we have a static library that has a global variable in it, and this static library is linked in to our main app, and in to a few of our plugins. Now on Linux, and on QNX, this global variable does not pose a problem. With a compilation switch, it is initialised correctly, and every time it is accessed, through a call from the main app or from a plugin, the variable is set to the value that it is supposed to be. So in this situation the global variable causes no issue, and is not the spawn of the underworld that it has been made out to be in software development lore.

At some point though, we decided that we need to have a Windows simulator. This made a tonne of sense, so a Windows port of our runtime was written. Now I understand. Now I get it. My eyes have been opened up to the inherit dangers that a global variable can cause.

You see, on Windows, the process and the plugin DLL both get a copy of the global variable. The problem this causes is that the main app has no way of initialising this variable to a value and have the DLL get that same value. Every time a new pluging DLL is loaded, it will have it's own copy of that global variable and it will be set to the initial default value.

There are tricks that you can try, such as setting up the variable in it's own section using pragma data_seg, or doing this sort or reverse export, whereby the main app is exporting symbols for the plugin DLL's to use. I have tried the pragma route, and I could not get it to work. Reading guides on the internet lead me to believe that the pragma's can be hit or miss. In my case it was a miss. I think it was due to the fact that the pragma had to be put in the static lib, so both the DLL and the main app end up executing the pragma. My next stab at fixing this problem will be to export said variable and functions from the static lib and main app, and have he DLL's use GetModuleHandle to find them in the main app. I think this will work, but it will add a bunch of defines based on OS in the plugins themselves as the code on Windows will have to use function handles to execute the desired functions, whereas the code for Linux and QNX can just make the calls. So I am not exactly enamoured with that solution either.

In the end a solution will be found, and it may well be that the global variable has to be removed. I realise that there are other reasons not to have global variables in your code. Having multiple pieces of code rely on a value that can be modified from a multitude of places can cause a lot of problems. I just found this one case has really hit home the point that you should try and avoid global variables.