Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 跨同一DLL的实例共享静态和全局变量_C++_Windows_Unix_Dll_Static - Fatal编程技术网

C++ 跨同一DLL的实例共享静态和全局变量

C++ 跨同一DLL的实例共享静态和全局变量,c++,windows,unix,dll,static,C++,Windows,Unix,Dll,Static,首先,有一些类似的问题,但没有一个真正解决了这个问题: 所以,我的问题是:我正在开发一个VST插件,我有一个在DLL中定义和实现的类。加载同一个DLL的多个实例,我想做的是维护一个“实例计数”,它监视类的构造次数(当按照VST标准加载DLL时,只发生一次) 一种简单的方法是创建一个类静态变量,我将其初始化为0,并在构造函数中递增/在析构函数中递减。我确信我知道我的类何时被构造和破坏,但我不确定的是这个类静态变量是否会在我的DLL实例之间共享 为了澄清,我多次加载同一个DLL;DLL中有一个类

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

所以,我的问题是:我正在开发一个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
    }
}
只有当应用程序加载DLL(即Windows上的::LoadLibrary)时,才会调用Foo的构造函数;只有当释放DLL(即Windows上的::FreeLibrary)时,才会调用析构函数。考虑这一点。s_InstanceCount是否会在调用构造函数时共享

编辑:
正如Serge在下面指出的,一个进程不能真正加载DLL两次。因此,当一个进程两次加载我的DLL时,构建的Foo实例存在于加载进程使用的相同内存空间中。也许…

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

向你解释这一点。但它也提供了一个很好的解决方案,可以使用。这将帮助您解决您的问题


编辑:显然还有另一种解决方案,创建共享数据段(即告诉链接器共享一些数据,就像它对代码所做的那样)。这里还有一个。我从未使用过它,因此它是否也适用于静态类成员还有待测试。

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

当然,instanceCount应该是原子的。。对,实际上我有一个关键部分,但我想要一个简单的示例。不,实际上您需要原子的,而不是关键部分<代码>垂直部分s仅在流程内工作,而非跨流程。请参见Serge的评论。这是同一个进程“重新加载”同一个DLL,这其实不是一件事,所以当DLL“重新加载”时,我实际上只是在访问相同的变量。所以我的问题措辞很糟糕,因为进程不可能重新加载DLL。但是,如果在同一个DLL上进行多个::LoadLibrary调用,那么在该DLL中访问的变量将在类实例之间共享(我认为)。您仍然应该使用
原子
。谢谢!我还需要一些角色。PS:与此同时,我已经尝试了共享片段的方法。虽然我可以让它与全局变量或静态变量一起工作,但我无法使静态类成员变量共享。共享数据段是一种遗留技术,应该避免使用,因为它们很有趣。@HarryJohnston。另一个限制似乎是仅使用简单数据,因为动态对象必然会在共享段之外分配内存,并通过指向non-shared memory.Hmmm导致未定义的行为。所以我想象的是,每当DLL被“重新加载”时,什么都不会发生;同一个进程正在访问同一DLL中的相同变量。这就是我想要的。谢谢您如何知道DLL已“重新加载”?我无法想象你所描述的会发生什么:当一个DLL被卸载时,属于它的变量应该被销毁,所以新加载的DLL应该得到新的变量。如果在卸载之前加载了两次呢?要扩展,VST3插件是一个DLL,由数字音频工作站(VST3主机)加载,并被视为一种工具或效果;同一个插件可以有多个实例,由主机决定如何管理。这就是我正在处理的情况,同一个插件有多个实例,它们“共享”同一个加载的DLL。@JohnJoseph,你是说DLL在同一个进程中加载多次还是在不同的进程中加载多次?