Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global variable has multiple copies on Windows and a single on Linux when compiled in both exec and shared libaray

Tags:

c++

linux

* Question revised (see below) *

I have a cpp file that defines a static global variable e.g.

static Foo bar;

This cpp file is compiled into an executable and a shared library. The executable may load the shared library at run time.

If I am on Linux there seem to be two copies of this variable. I assume one comes from the executable and one from the shared library. Other platforms (HP, Windows) there seems to be only one copy.

What controls this behavior on Linux and can I change it? For example is there a compiler or linker flag that will force the version of this variable from the shared library to be the same as the one from the executable?

* Revision of question *

Thanks for the answers so far. On re-examining the issue it is not actually the problem stated above. The static global variable above does indeed have multiple copies on Windows, so no difference to what I see on Linux.

However, I have another global variable (not static this time) which is declared in a cpp file and as extern in a header file.

On Windows this variable has multiple copies, one in the executable and one in each dll loaded up, and on Linux it only has one. So the question is now about this difference. How can I make Linux have multiple copies?

(The logic of my program meant the value of the static global variable was dependent of the value of the non-static global variable and I started accusing the wrong variable as being the problem)

like image 607
Reuben Avatar asked Feb 07 '11 18:02

Reuben


3 Answers

I strongly suggest you read the following. Afterwards, you will understand everything about shared libraries in Linux. As said by others, the quick answer is that the static keyword will limit the scope of the global variable to the translation unit (and thus, to the executable or shared library). Using the keyword extern in the header, and compiling a cpp containing the same global variable in only one of the modules (exe or dll/so) will make the global variable unique and shared amongst all the modules.

EDIT: The behaviour on Windows is not the same as on Linux when you use the extern pattern because Windows' method to load dynamic link libraries (dlls) is not the same and is basically incapable of linking global variables dynamically (such that only one exists). If you can use a static loading of the DLL (not using LoadLibrary), then you can use the following:

//In one module which has the actual global variable:
__declspec(dllexport) myClass myGlobalObject;
//In all other modules:
__declspec(dllimport) myClass myGlobalObject;

This will make the myGlobalObject unique and shared amongst all modules that are using the DLL in which the first version of the above is used.

If you want each module to have its own instance of the global variable, then use the static keyword, the behaviour will be the same for Linux or Windows.

If you want one unique instance of the global variable AND require dynamic loading (LoadLibrary or dlopen), you will have to make an initialization function to provide every loaded DLL with a pointer to the global variable (before it is used). You will also have to keep a reference count (you can use a shared_ptr for that) such that you can create a new one when none exist, increment the count otherwise, and be able to delete it when the count goes to zero as DLLs are being unloaded.

like image 67
Mikael Persson Avatar answered Sep 28 '22 17:09

Mikael Persson


The static qualifier applied to a namespace variable means that the scope of the variable is the translation unit. That means that if that variable is defined in a header and you include it from multiple .cpp files you will get a copy for each. If you want a single copy, then mark it as extern (and not static) in the header, define it in a single translation unit and link that in either the executable or the library (but not both).

like image 36
David Rodríguez - dribeas Avatar answered Sep 28 '22 18:09

David Rodríguez - dribeas


What compiler did you use on each of these platforms? The behavior you're describing for Linux would be what I'd expect, the static global is only local to that particular file at compile time.

like image 36
stackmate Avatar answered Sep 28 '22 17:09

stackmate