John Joseph
John Joseph

Reputation: 125

Sharing static and global variables across instances of the same DLL

First off, there are some similar questions to this, but none really address the exact issue:

https://social.msdn.microsoft.com/forums/vstudio/en-US/b7701ee5-c9fa-4693-8ae1-d59736360514/question-about-static-variables-in-dll

http://cboard.cprogramming.com/cplusplus-programming/101543-global-static-variable-class-delivered-dll.html

So, here's my question: I'm working on a VST plugin, and I have a class that is defined and implemented within a DLL. Multiple instances of this same DLL are loaded, and what I'd like to do is maintain an "instance count" that monitors how many times the class is constructed (which only occurs once, when the DLL is loaded per the VST standard.)

One straightforward way of doing this would be to create a class static variable that I initialize to 0 and increment in the constructor / decrement in the destructor. I'm confident that I know when my class is constructed and destructed, but what I'm unsure of is whether or not this class static variable will be shared across instances of my DLL.

To clarify, I am loading the same DLL multiple times; within the DLL is a class (used only within the DLL code, and not exposed to the application.) There is some discussion on whether or not the behavior of data defined in DLLs varies between Windows and Unix, so I'd like to know if doing this kind of thing within a DLL is safe for cross platform use.

An example class, defined within the DLL, and not exposed in any way to the application loading the DLL (or otherwise.)

Header File

// Foo.h
# pragma once
class Foo {
    static int s_InstanceCount;
public:
    Foo();
    ~Foo();
};

And now the source file

// Foo.cpp
#include "Foo.h"
int Foo::s_InstanceCount = 0;

Foo::Foo() {
    s_InstanceCount++;
}

Foo::~Foo() {
    s_InstanceCount--;
    if (s_InstanceCount == 0) {
        // Do something
    }
}

The constructor of Foo is only called when the DLL is loaded by an application (i.e ::LoadLibrary on Windows), and the destructor is only called when the DLL is freed (i.e ::FreeLibrary on Windows). Consider that guaranteed. Will s_InstanceCount be shared across calls to the Constructor?

EDIT: As Serge points out below, a process can't really load a DLL twice. So, when my DLL is loaded twice by one process, the Foo instances that get constructed exist within the same memory space used by the loading process. Maybe...

Upvotes: 4

Views: 5727

Answers (2)

Serge Rogatch
Serge Rogatch

Reputation: 15020

No, s_InstanceCount in your example will be private to each instance of the DLL. Furthermore, without tweaking the file name of the DLL you normally can't load it multiple times in the same process, as explained here: Load the same dll multiple times . If the DLL instances are in different processes in your case, then you need inter-process communication e.g. via shared memory .

Upvotes: 1

Christophe
Christophe

Reputation: 73366

The DLL is just shared code that is run in the address space of the processes calling it. Every process gets its own copy of the global/static variables defined in the DLL.

This article explains this to you. But it also gives a nice workaround to share data accross several processes using a file mapping. This should help you solve your issue.

Edit: There is apparently another solution, creating a shared data segment (i.e. tell the linker to share some of the data, like it does for the code). Here microsoft doc and and a proof of concept on codeproject. I have never used it, so it remains to be tested if it works for static class members as well.

Upvotes: 6

Related Questions