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

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

问题描述

假设我在C ++中写了一个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?

推荐答案

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

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.

现在,三个问题:

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

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 - 不保证构造对象或不同编译单元(即CPP文件)的顺序,因此您不能希望对象A将如果两个对象在两个不同的CPP中被实现,则在B之前构建。这是很重要的,如果B依赖于A.解决方案是移动在同一个CPP文件中的所有全局对象,如在同一个编译单元内,对象的实例顺序将是构造的顺序(和顺序的逆的破坏)

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 - 有些东西在DllMain中被禁止做。这些东西也可能被禁止,在构造函数。所以避免锁定东西。请参阅Raymond Chen关于此主题的精彩网志:

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

在这种情况下,延迟初始化可能很有趣:类保持在未初始化状态(内部指针为NULL,布尔值为假, ),直到你调用他们的方法,在这一点,他们将初始化自己。如果你使用main(或主要的后代函数)中的那些对象,你会确定,因为他们会在执行DllMain后被调用。

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 - 当然,如果DLL A中的某些全局对象依赖于DLL B中的全局对象,那么您应该非常小心DLL加载顺序,因此依赖关系。在这种情况下,具有直接或间接循环依赖性的DLL将导致你疯狂的头痛。最好的解决方案是打破循环依赖。

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.

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

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天全站免登陆