c++ - 神秘的全局变量 - COM/STA 单元对象

标签 c++ dll com components atl

场景如下:

-COM DLL,加载到使用该 DLL 的进程的地址空间中。 -在 DLL 中存在一对全局变量(比如 var a、var b)和一个全局函数。 - 进程启动,调用全局函数并初始化全局变量 a、b 并调用 CoInitialize(NULL) - 该线程是一个 STA。 -然后相同的全局函数创建一个 STA COM 对象

稍后在程序中,同一个线程(上面调用 CoInitialize 并创建 STA COM 对象的线程)在此 DLL 中调用同一个全局 C 函数(我们称之为 func())。在 C 函数的范围内,全局变量的状态完全符合预期(即正确初始化)。 函数 func() 在现有 STA COM 对象上调用 COM 方法的那一刻,同一 DLL 中的 COM 对象看到全局变量(var a,var b)的完全不同的拷贝。我获取了这两个变量的地址,它们在 C-func 中与调用的 COM 对象函数完全不同。 到底是怎么回事?我认为同一地址空间中的全局变量应该是全面可见的。

最佳答案

可能正在加载您的 DLL 的两个实例——一个由托管您的 DLL 的应用程序显式加载,第二个通过 CoCreateInstance 通过 COM 子系统加载。前者将在 DLL 搜索路径中查找应用程序进程,而后者将在注册表中查找实现 COCLASS 的 COM 组件的位置。

如果您的 DLL 有 DllMain(如果它是基于 MFC 的 DLL,则有 InitInstance 函数),那么您可以对其断点并查看 hinstance 参数(如果是 MFC,则为 AfxGetInstanceHandle)以查看是否 (a) 您初始化了两次并且(b) 您看到两个不同的 DLL 实例句柄。如果是这样,那么您肯定加载了两次。

DLL 在文件系统中的位置很重要,因此您应该查看是否有位于不同位置的拷贝,这些拷贝可能会根据我上面提到的规则单独加载。

一般来说,COM DLL 不应该被直接加载。您应该将您的功能分解为两个 DLL,其中一个 COM 服务器 DLL 专用于 COM 内容。如果您愿意,您可以为自己提供一个内部 COCLASS 接口(interface),使您能够将全局变量传递给 COM DLL。

关于c++ - 神秘的全局变量 - COM/STA 单元对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5480633/

相关文章:

python - py2exe在导入opencv时由于缺少DLL而无法创建EXE

delphi - 如何将 (Delphi) OLE 服务器与第二个客户端重用?

c# - COM DLL 依赖项中静态 DLL 数据的多个进程和拷贝

c++ - 创建翻译器;需要从文本文件正确插入

c++ - c++/cx 中的 storagefile::ReadAsync 异常?

c# - 括号和赋值运算符顺序

c# - SQL Server 中的 CLR 程序集 C#

java - 编译开源数据包捕获软件

c# - 将通用 Windows C# 类库引用添加到通用 Windows C++ DLL 项目 Visual Studio 2015

c++ - Visual C++ - 找到一个或多个多次定义的符号