jbreaux

The code below is a simple example that displays some behavior that I do not understand. I have a Visual C++ solution that creates a simple console application. The solution contains a Win32 console application project, a static library project, and a dll project. The console application project contains main.cpp:

//########## BEGIN main.cpp

#include "MyDLLClass.h"
#include "MyStaticLibClass.h"

int main() {

MyStaticLibClass mslc;
mslc.changeInt(2);

MyDLLClass mdc;
mdc.DllFunc();

}

//########## END main.cpp

The static library project contains MyStaticLibClass.h and MyStaticLibClass.cpp:

//########## BEGIN MyStaticLibClass.h

class MyStaticLibClass {

public:
void changeInt(int _Int);
};

//########## END MyStaticLibClass.h

//########## BEGIN MyStaticLibClass.cpp

#include "MyStaticLibClass.h"

int myGlobalInt = 0;
static int myStaticGlobalInt = 0;

void MyStaticLibClass::changeInt(int _Int) {
myGlobalInt = _Int;
myStaticGlobalInt = _Int;
}

//########## END MyStaticLibClass.cpp

Finally, the dll project contains MyDLLClass.h and MyDLLClass.cpp:

//########## BEGIN MyDLLClass.h

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else // #ifdef DLL_EXPORTS
#define DLL_API __declspec(dllimport)
#endif // #ifdef DLL_EXPORTS

class DLL_API MyDLLClass {
public:
void DllFunc();
};

//########## END MyDLLClass.h

//########## BEGIN MyDLLClass.cpp

#include "MyDLLClass.h"
#include "MyStaticLibClass.h"

void MyDLLClass::DllFunc() {

MyStaticLibClass mslc;
mslc.changeInt(4);

}

//########## END MyDLLClass.cpp

You can see that at runtime, MyStaticLibClass::changeInt() will first be called from the exe and then from the dll. The first time that MyStaticLibClass::changeInt() is entered, the global variables myGlobalInt and myStaticGlobalInt are both equal to 0 (as they should be). As the program exits from MyStaticLibClass::changeInt(), myGlobalInt and myStaticGlobalInt are equal to 2 (as they should be).

The behavior that I do not understand occurs the second time that MyStaticLibClass::changeInt() is entered (i.e., when it is called from the dll). At this time, the global variables are equal to 0 again (i.e., the values they are assigned when they are declared).

The following are the memory addresses of the global variables during each pass through MyStaticLibClass::changeInt():

First pass (called from the exe):
&myGlobalInt 0x00417178
&myStaticGlobalInt 0x0041717c

Second pass (called from the dll):
&myGlobalInt 0x10017168
&myStaticGlobalInt 0x1001716c

So it appears that two instances of each global variable are being created (even the file-static variable, myStaticGlobalInt); one instance is used by the code in the exe and the other instance is used by the code in the dll. Is this expected behavior Is there any way to prevent the second instance from being created and to ensure that the exe and dll will both be accessing the same instance of each global variable

Thank you,

Jim



Re: Visual C++ Language Two instances of global variable created when DLL depends on static library

Mike Danes

"So it appears that two instances of each global variable are being created (even the file-static variable, myStaticGlobalInt); one instance is used by the code in the exe and the other instance is used by the code in the dll. Is this expected behavior "

Yes. A static library means that the code and variables it contains are linked in each dll/exe that use it. Not only the variables are duplicated but also the code for function changeInt will exist in both dll and exe. It basically behaves as if you have MyStaticLib.cpp files compiled in both dll and exe projects.

"Is there any way to prevent the second instance from being created and to ensure that the exe and dll will both be accessing the same instance of each global variable "

Not if you are using a static lib. You need to use a dll for this (or depending on specific situation you can link the static lib only into the existing dll).





Re: Visual C++ Language Two instances of global variable created when DLL depends on static library

einaros

Would it break your design to invert the control somewhat Keep the variables in the dll, and have both the main project and static library call into that to change them. That will work as you expect it to.




Re: Visual C++ Language Two instances of global variable created when DLL depends on static library

jbreaux

Hi Mike,

Thank you very much for your helpful response. A few follow-up questions:

1. Is this behavior specific to the Microsoft linker, or would I see this behavior using any linker on Windows

2. Are all variables and all code from the static lib replicated in the dll even if they are not referenced in any way by the code in the dll

3. The same code in my example works the way I intended when I build it on Linux using gcc (building the MyDLLClass project as a shared library). Do you know why it works in this case

Thanks again,

Jim





Re: Visual C++ Language Two instances of global variable created when DLL depends on static library

jbreaux

Hi Einar,

Thank you for the suggestion. I will try to solve the problem doing something similar. I do not want to take the variables in question from the static library project and put them in the dll project corresponding to the one in the example. Instead I will move the variables (and the class that accesses them) to a new dll project (i.e. there will be two dlls).

Thanks,
Jim





Re: Visual C++ Language Two instances of global variable created when DLL depends on static library

Mike Danes

"1. Is this behavior specific to the Microsoft linker, or would I see this behavior using any linker on Windows "

I don't know much about other linkers on Windows but I believe this is an OS characteristic, not a linker one. The way DLLs work is that every DLL/EXE has access to its own symbols (variables/functions etc.) even if another DLL/EXE contains a variable/function with the same name.

"2. Are all variables and all code from the static lib replicated in the dll even if they are not referenced in any way by the code in the dll "

Normally unused variables are discarded when building with compiler optimizations turned on.

"3. The same code in my example works the way I intended when I build it on Linux using gcc (building the MyDLLClass project as a shared library). Do you know why it works in this case "

As far as I know on Linux dynamic link libraries (.so) files work differently than Windows .dll files. On Linux if 2 .so files (or a .so file and the executable itself) contain a variable (or function) with the same name only one will get used.