当前位置:  开发笔记 > 编程语言 > 正文

DLL中声明的全局变量会发生什么?

如何解决《DLL中声明的全局变量会发生什么?》经验,为你挑选了2个好方法。

假设我用C++编写一个DLL,并使用一个非平凡的析构函数声明一个类的全局对象.卸载DLL时是否会调用析构函数?



1> paercebal..:

在Windows C++ DLL中,所有全局对象(包括类的静态成员)将在使用DLL_PROCESS_ATTACH调用DllMain之前构造,并且在使用DLL_PROCESS_DETACH调用DllMain之后它们将被销毁.

现在,您必须考虑三个问题:

0 - 当然,全局非const对象是邪恶的(但你已经知道了,所以我将避免提到多线程,锁,神对象等)

1 - 不保证对象或不同编译单元(即CPP文件)的构造顺序,因此如果两个对象在两个不同的CPP中实例化,则无法希望在B之前构造对象A. 如果B依赖于A,这很重要.解决方案是将所有全局对象移动到同一个CPP文件中,因为在同一个编译单元内,对象的实例化顺序将是构造的顺序(以及顺序的反转)破坏)

2 - 在DllMain中有些事情是被禁止的.在构造函数中,这些东西也可能被禁止.所以避免锁定某些东西 请参阅Raymond Chen关于此主题的优秀博客:

http://blogs.msdn.com/oldnewthing/archive/2004/01/27/63401.aspx

http://blogs.msdn.com/oldnewthing/archive/2004/01/28/63880.aspx

在这种情况下,延迟初始化可能很有趣:类仍处于"未初始化"状态(内部指针为NULL,布尔值为假,无论如何),直到您调用其中一个方法,此时它们将自己初始化.如果你在main(或者一个main的后代函数)中使用那些对象,你就可以了,因为它们将在执行DllMain后被调用.

3 - 当然,如果DLL A中的某些全局对象依赖于DLL B中的全局对象,则应该非常小心DLL加载顺序,从而确保依赖性.在这种情况下,具有直接或间接循环依赖性的DLL将导致您疯狂的头痛.最好的解决方案是打破循环依赖.

PS:请注意,在C++中,构造函数可以抛出,并且您不希望在DLL加载过程中出现异常,因此请确保您的全局对象在没有非常好的理由的情况下不会使用异常.由于正确编写的析构函数无权抛出,因此在这种情况下DLL卸载应该没问题.


如果一个流程更改了全局值,那么是否会在另一个流程中观察到更改?
@ LB--:通常,不是:每个进程都有自己的全局变量*除非你碰巧将它们映射到共享内存中,或者使用特定于操作系统的技巧使它们在使用该DLL的所有进程之间共享(我不记得了)完全是Windows上的技巧,但它涉及#pragma声明,IIRC)

2> Mark Ransom..:

Microsoft的这个页面详细介绍了DLL初始化和全局变形的破坏:http:
//msdn.microsoft.com/en-us/library/988ye33t.aspx

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有