DLL卸载程序

时间:2016-04-20 15:51:45

标签: c++ dll

我确实解决了眼前的问题,但现在我需要了解为什么它会被解决。 ; - )

所以我还有几个问题。

假设我有一个从DLL导出的类。现在每次调用时都应该将这个DLL加载到内存中:

MyExportedClass *pb = new MyExportedClass;

它应该留在内存中,只有在我打电话时才会被卸载:

delete pb;

这是对的吗?

如果我理解正确并且上一个问题的答案是肯定的,那么在以下情况中会发生什么:

我有一个从dll(dll1)导出的接口,我的实现是从另一个dll(dll2)导出的。所以每次执行时都会:

MyInterface *pInterface = new MyImplementation;

这两个dll都应该加载到内存中,它们应该保留在内存中,直到我打电话:

delete pInterface;

这是对的吗?

现在,如果这个问题的答案是肯定的 - 我是否有控制/说法,哪个库将首先卸载,哪个库将是第二个?或者卸载将始终在调用相应类的析构函数后立即发生?

现在,是否有一个工具可以检查库是否已卸载以及何时卸载?我可以只使用假的DllMain()并检查它的process_detach情况,但我的印象总是:当库导出函数时使用DllMain,而当库导出类时不使用DllMain。我从MSVC 5/6开始使用这种方法(遵循其中一本关于C ++的书)。

我错了,在这两种情况下我仍然可以使用DLLMain吗?

谢谢。

1 个答案:

答案 0 :(得分:1)

DLL加载可以是自动的(如果在导入表中列出)或手动(使用LoadLibrary)。一些托管框架,比如.NET,当他们在元数据中看到DLL导入声明时,会默默地为你调用LoadLibrary,但C ++不是其中之一。 C ++最接近的是延迟加载,其中调用LoadLibrary的函数(默认情况下,您可以替换自己的函数)由编译器提供。

另一方面,DLL卸载始终是手动的。删除对象永远不会隐式卸载DLL。您必须致电FreeLibrary(或FreeLibraryAndExitThread)。最好不要在该库中定义的对象仍在使用时调用FreeLibrary

现在,Windows中的COM系统有点复杂,因为它为您管理DLL生命周期。但DLL生存期仍然不受对象删除控制,而是通过调用DLL中的DllCanUnloadNow函数来控制。通常,您需要维护活动对象的计数才能正确编写该函数。但它仍然需要你的手动实现,你可以简单地总是返回false从不卸载(这在开发过程中有点痛苦,因为你必须关闭整个应用程序来尝试新的插件版本等...但实际上是免费的无论如何,每次使用DLL并成功卸载它都是罕见的。

当然,没有什么可以自动卸载导入表中列出的DLL,无论是创建还是销毁了多少个对象实例,它们都会在进程启动期间加载并且永远不会卸载。