Visual C++

如何与应用程序或其他 DLL 共享自己 DLL 中的数据?

Win32 DLL 映射到调用进程的地址空间中。默认情况下,每个使用 DLL 的进程都有自己的所有 DLL 全局变量和静态变量的实例。如果 DLL 需要与它的由其他应用程序加载的其他实例共享数据,则可使用下列方法之一:

使用 data_seg 杂注创建命名数据节。

使用内存映射文件。请参见有关内存映射文件的 Win32 文档。

以下是一个使用 data_seg 杂注的示例:

复制代码

#pragma data_seg (".myseg")

int i = 0;

char a[32]n = "hello world";

#pragma data_seg()

data_seg 可用于创建新的命名节(在此示例中为 .myseg)。为清楚起见,最典型的用法是调用数据段 .shared。然后必须在 .def 文件中或者使用链接器选项 /SECTION:.MYSEC,RWS 为这个新的命名数据节指定正确的共享属性。

在使用共享数据段之前要考虑下列限制:

必须静态初始化共享数据段中的所有变量。在上面的示例中,i 初始化为 0,而 a 是初始化为“hello world”的 32 个字符。

所有共享变量放在编译 DLL 的指定数据段中。很大的数组可产生很大的 DLL。对于所有已初始化的全局变量都是如此。

永远不要将特定于进程的信息存储在共享数据段中。大多数 Win32 数据结构或值(如 HANDLE)仅在单个进程的上下文内才真正有效。

每个进程都将获取它自己的地址空间。永远不要将指针存储在共享数据段包含的变量中,这一点很重要。指针可能在某个应用程序中完全有效,但在另一个应用程序中却无效。

DLL 本身有可能加载到每个进程的虚拟地址空间中的不同地址。具有指向 DLL 中的函数或指向其他共享变量的指针是不安全的。

请注意,上述最后三点适用于内存映射文件和共享数据段。

内存映射文件优于共享数据节,原因是内存映射文件的起始位置是已知的。开发人员通过使用距离位于共享内存内的所有数据中的“共享内存节的起始位置的偏移量”,可以实现类似于指针的行为。为使此操作快速简便,强烈建议使用 __based 指针。但一定要记住:在每个进程中,基(或内存映射文件的起始位置)可能不同,因此存储 __based 指针的基的变量自身不能位于共享内存中。

这些限制对 C++ 类有重要的含义。

具有虚函数的类总是包含函数指针。具有虚函数的类永远不应存储在共享数据段中,也不应存储在内存映射文件中。这对于 MFC 类或从 MFC 继承的类尤其重要。

静态数据成员以全局变量的等效形式实现。这意味着每个进程都具有它自己的该类静态数据成员的副本。不应共享具有静态数据成员的类。

对于 C++ 类,共享数据段的初始化要求引起一个特定问题。如果共享数据段中有类似 CTest Counter(0); 的内容,则当每个进程加载 DLL 时,Counter 对象将在该进程中初始化,从而有可能每次都将对象的数据清零。这与内部数据类型(由链接器在创建 DLL 时初始化)非常不同。

由于存在这些限制,Microsoft 不建议在进程之间共享 C++ 对象。一般情况下,如果希望使用 C++ 在进程之间共享数据,请编写在内部使用内存映射文件来共享数据的类,但不要共享类实例本身。在开发这样的类时,可能需要特别小心,但它使应用程序开发人员能够完全控制共享数据的副作用。

有关创建命名数据节的更多信息,请参见位于 http://support.microsoft.com/default.aspx?ln=zh-cn 上的下列知识库文章:

“How to Share Data Between Different Mappings of a DLL”(如何在 DLL 的不同映射之间共享数据)。

“Specifying Shared and Nonshared Data in a DLL”(指定 DLL 中的共享数据和非共享数据)(Q100634)。

“Sharing All Data in a DLL”(共享 DLL 中的所有数据)。

“Memory in Shared Code Sections Is Not Shared Across Terminal Server Sessions”(共享代码节中的内存不在终端服务器会话间共享)

dll共享段中一些需要注意的问题的更多相关文章

  1. DLL函数中内存分配及释放的问题

    DLL函数中内存分配及释放的问题 最近一直在写DLL,遇到了一些比较难缠的问题,不过目前基本都解决了.主要是一些内存分配引起问题,既有大家经常遇到的现象也有特殊的 情况,这里总结一下,做为资料. 错误 ...

  2. C#调用其它语言(例如C++)DLL文件中函数的方法摘要

    有托管和非托管的概念没仔细看,接下来记录的引用Dll文件指的是无法通过VS自动完成添加引用的情况,可以使用如下方法: 步骤一: 打开“Visual Studio Tools”的“命令提示符”工具 使用 ...

  3. 在DLL动态链接库中封装VCL的MDI子窗体

    在DLL动态链接库中封装VCL的MDI子窗体不多说了,看代码就应该明白了,曾经我遇到的问题,现在放出来大家共享! 这里是工程文件的部分: 在DLL中封装MDI子窗体需要重写DLL入口函数,具体代码如下 ...

  4. C# -- 使用反射(Reflect)获取dll文件中的类型并调用方法

    使用反射(Reflect)获取dll文件中的类型并调用方法 需引用:System.Reflection; 1. 使用反射(Reflect)获取dll文件中的类型并调用方法(入门案例) static v ...

  5. XML序列化 判断是否是手机 字符操作普通帮助类 验证数据帮助类 IO帮助类 c# Lambda操作类封装 C# -- 使用反射(Reflect)获取dll文件中的类型并调用方法 C# -- 文件的压缩与解压(GZipStream)

    XML序列化   #region 序列化 /// <summary> /// XML序列化 /// </summary> /// <param name="ob ...

  6. 从加载DLL的中获取放置于Resources文件夹中资源字典的几种方法

    原文:从加载DLL的中获取放置于Resources文件夹中资源字典的几种方法 主程序 为 Main_Test.exe 被加载的DLL 为 Load_Test.dll  此DLL 中 有一个 文件夹Re ...

  7. VC 使用msxml6.dll动态链接库中的函数读写XML文件

    VC 使用msxml6.dll动态链接库中的函数读写XML文件 目录 1 引言 2 .dll使用方法 3 常用函数总结 4 实例应用 5 运行效果预览 6 补充说明 7 不足之处 8 更新   引言: ...

  8. 【NX二次开发】NX内部函数,pskernel.dll文件中的内部函数

    pskernel.dll文件中的内部函数,含有部分pk函数,用法可以查看pk函数帮助: ADPAPE ADVXED APPTRA ATGETO ATTGEO BLECHK BLECRB BLECVR ...

  9. 加载dll过程中assembly失败

    错误现象: 进行插件读取时出现错误:“尝试从一个网络位置加载程序集,在早期版本的 .NET Framework 中,这会导致对该程序集进行沙盒处理.此发行版的 .NET Framework 默认情况下 ...

随机推荐

  1. 1,VMware与Centos系统安装

    选择性 pc可以选择 -纯系统 Linux/windows -双系统 Windows+Linux -虚拟化技术 Windows+vmware workstation 服务器 -物理机纯系统 -物理机+ ...

  2. CSS计数器(自定义列表)

    概念 CSS3计数器(CSS Counters)可以允许我们使用css对页面中的任意元素进行计数,实现类似于有序列表的功能(自定义有序列表) 与有序列表相比,它的突出特性在于可以对任意元素计数,同时实 ...

  3. 算法:枚举法---kotlin

    枚举法:效率低,循环所有的情况,找到正确答案 用于解决数学问题,还是很简单的. 比如,奥数里面: 算 法 描 述 题X题=题题题题题题 其中 算法描述题每一个为一个数字,请写出正确的数字. ok,我们 ...

  4. 微信支付 h5

    Android开发要点说明 商户在微信开放平台申请开发应用后,微信开放平台会生成APP的唯一标识APPID.由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付. ...

  5. 部署微软Nano Server的好处是什么?

    虚拟化对数据中心效率和硬件利用率产生了戏剧性的影响,但是接下来有关系统整合的主要责任落 在了操作系统的重量上.虚拟机通常运行企业级操作系统,比如Windows Server,但是Windows Ser ...

  6. static任我行- 为人不注意的static

    前几天一直在想,static方法如果没有被调用,会不会分配内存的问题,查了一下资料,终于得到了一个官方的说法了. static 方法调用:使用比较频繁的时候使用,像数据库连接串,Connection ...

  7. day06_04 购物车讲解02

    1.0 补充知识 a,b = [2,3] print(a) print(b) #>>>2 #>>>3 a,b = (2,3) print(a) print(b) # ...

  8. spring boot打war包启动Tomcat失败

    Tomcat启动失败:最后一个causy by :java.lang.NoSuchMethodError: org.apache.tomcat.util.res.StringManager.getMa ...

  9. pyinstaller打包自己的python程序

    使用Pyinstaller打包步骤如下 1. 安装pyinstaller pip install pyinstaller 查看安装的版本 pyinstaller --version 2. 给脚本加密 ...

  10. 软件工程概论课堂测试一————添加新课程(web)

    设计思想 三个文件Class_add.java  add.jsp  addInput.jsp Class_add.java : 内封装方法:连接数据库.向数据库添加课程信息.判断非合理的输入情况.判断 ...