在DLL中声明的全局变量会发生什么? [英] What happens to global variables declared in a DLL?

查看:154
本文介绍了在DLL中声明的全局变量会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我用C ++编写一个DLL,并声明一个具有非平凡析构函数的类的全局对象。在卸载DLL时,会调用析构函数吗?

解决方案

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



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



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



1 - 对象或不同编译单元(即CPP文件)的构造顺序不能保证,所以您不能希望对象A将如果两个对象在两个不同的CPP中实现,则在B之前构建。如果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,布尔值为false,无论如何),直到您调用其中一个方法,此时它们将自动初始化。如果您在主(或其中一个主要的后代)函数中使用这些对象,那么您将会很好,因为在执行DllMain后将被调用。



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



PS:请注意,在C ++中,构造函数可以抛出,并且您不想在DLL的中间出现异常加载,所以要确保你的全局对象不会使用异常没有非常好的理由。由于正确编写的析构函数没有被授权,所以DLL卸载在这种情况下应该是可以的。


Let's say I write a DLL in C++, and declare a global object of a class with a non-trivial destructor. Will the destructor be called when the DLL is unloaded?

解决方案

In a Windows C++ DLL, all global objects (including static members of classes) will be constructed just before the calling of the DllMain with DLL_PROCESS_ATTACH, and they will be destroyed just after the call of the DllMain with DLL_PROCESS_DETACH.

Now, you must consider three problems:

0 - Of course, global non-const objects are evil (but you already know that, so I'll avoid mentionning multithreading, locks, god-objects, etc.)

1 - The order of construction of objects or different compilation units (i.e. CPP files) is not guaranteed, so you can't hope the object A will be constructed before B if the two objects are instanciated in two different CPPs. This is important if B depends on A. The solution is to move all global objects in the same CPP file, as inside the same compilation unit, the order of instanciation of the objects will be the order of construction (and the inverse of the order of destruction)

2 - There are things that are forbidden to do in the DllMain. Those things are probably forbidden, too, in the constructors. So avoid locking something. See Raymond Chen's excellent blog on the subject:

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

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

In this case, lazy initialization could be interesting: The classes remain in an "un-initialized" state (internal pointers are NULL, booleans are false, whatever) until you call one of their methods, at which point they'll initialize themselves. If you use those objects inside the main (or one of the main's descendant functions), you'll be ok because they will be called after execution of DllMain.

3 - Of course, if some global objects in DLL A depend on global objects in DLL B, you should be very very careful about DLL loading order, and thus dependancies. In this case, DLLs with direct or indirect circular dependancies will cause you an insane amount of headaches. The best solution is to break the circular dependancies.

P.S.: Note that in C++, constructor can throw, and you doesn't want an exception in the middle of a DLL loading, so be sure your global objects won't be using exception without a very very good reason. As correctly written destructors are not authorized to throw, the DLL unloading should be ok in this case.

这篇关于在DLL中声明的全局变量会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆