在同一DLL的实例之间共享静态和全局变量

时间:2015-11-03 15:46:59

标签: c++ windows unix dll static

首先,有一些类似的问题,但没有一个真正解决确切的问题:

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

所以,这就是我的问题:我正在开发一个VST插件,我有一个在DLL中定义和实现的类。加载了同一个DLL的多个实例,我想要做的是保持"实例计数"监视类的构造次数(当按照VST标准加载DLL时,它只发生一次。)

这样做的一种简单方法是创建一个类静态变量,我将其初始化为0并在析构函数中的构造函数/减量中递增。我确信我知道什么时候构建和销毁我的类,但我不确定的是这个类静态变量是否会在我的DLL实例之间共享。

为了澄清,我多次加载相同的DLL; DLL中是一个类(仅在DLL代码中使用,而不是暴露给应用程序。)关于DLL中定义的数据行为是否因Windows和Unix之间的不同而有所讨论,所以我喜欢要知道在DLL中执行此类操作对于跨平台使用是否安全。

在DLL中定义的示例类,不以任何方式暴露给加载DLL的应用程序(或其他方式。)

标头文件

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

现在是源文件

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

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

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

Foo的构造函数仅在应用程序加载DLL时调用(即Windows上的:: LoadLibrary),并且仅在释放DLL时调用析构函数(即Windows上的FreeLibrary)。考虑到保证。是否会在对构造函数的调用之间共享s_InstanceCount?

编辑: 正如Serge在下面指出的那样,一个进程无法真正加载DLL两次。因此,当我的DLL被一个进程加载两次时,构造的Foo实例存在于加载过程使用的相同内存空间中。也许...

2 个答案:

答案 0 :(得分:4)

DLL只是在调用它的进程的地址空间中运行的共享代码。每个进程都获得自己的DLL中定义的全局/静态变量的副本。

This article向您解释。但它也提供了一个很好的解决方法,可以使用file mapping在多个进程中共享数据。这可以帮助您解决问题。

编辑: 显然有另一种解决方案,创建一个共享数据段(即告诉链接器共享一些数据,就像它对代码一样)。这里microsoft docproof of concept on codeproject。我从来没有使用它,所以它仍然需要测试它是否适用于静态类成员。

答案 1 :(得分:1)

不,您示例中的s_InstanceCount将对DLL的每个实例都是私有的。此外,如果不调整DLL的文件名,通常无法在同一进程中多次加载它,如下所述:Load the same dll multiple times。 如果DLL实例在您的情况下处于不同的进程中,那么您需要进程间通信,例如通过shared memory