C ++ DLL卸载析构函数?

时间:2012-04-14 23:57:00

标签: c++ windows winapi dll

所以我有一个用C ++编写的DLL。 但是,它使用GlobalAlloc()分配内存。为了避免内存泄漏,我想跟踪这些分配并在销毁DLL时解除所有这些分配。

有没有办法编写一个在卸载DLL时调用的函数? 我能想到的一件事是在我的DLL中创建一个全局对象,并在其析构函数中编写无内存调用,但这似乎有些过分。 我的另一个想法是在DLL卸载时依靠操作系统释放内存,但这看起来很脏。

由于

3 个答案:

答案 0 :(得分:6)

  

有没有办法编写一个在卸载DLL时调用的函数?我能想到的一件事是在我的DLL中创建一个全局对象,并在其析构函数中编写无内存调用

这是可能的,虽然我完全相信你的对象的析构函数将被调用时将是未定义的。

您可能对DLL_PROCESS_DETACH感兴趣,虽然您应该避免在DllMain中执行任何重要操作,但似乎可以在此处取消分配资源。请注意警告:

  

当由于DLL加载失败,进程终止或FreeLibrary调用而从进程卸载DLL时,系统不会使用DLL_THREAD_DETACH值调用DLL的入口点函数。过程的各个线程。该DLL仅发送DLL_PROCESS_DETACH通知。 DLL可以利用这个机会清理DLL已知的所有线程的所有资源。

     

当处理DLL_PROCESS_DETACH时,只有在动态卸载DLL时(lpReserved参数为NULL),DLL才应释放堆内存等资源。如果进程正在终止(lpvReserved参数为非NULL),则除当前线程之外的进程中的所有线程已经退出或已通过调用ExitProcess函数显式终止,这可能会留下一些进程资源,例如堆处于不一致的状态。在这种情况下,DLL清理资源是不安全的。相反,DLL应该允许操作系统回收内存。

您可能需要详细说明为什么您的DLL可以保留在内存中,如果您有许多DLL创建的对象,它们应该有一个已定义的生命周期并在它们结束时自行清理寿命。

如果它们不是对象(即内存被分配并通过函数返回给调用者),为什么不将责任归还给使用DLL的人?他们可以释放记忆。终端服务库遵循此模式(WTSFreeMemory)。

如果资源是长期存在且必须存在于库的生命周期中,请让使用者控制库的生命周期。根据需要编写两个函数:MyFrameworkStartupMyFrameworkShutdown。 Winsock遵循这种模式(WSAStartupWSACleanup)。

  

我的另一个想法是在DLL卸载时依赖操作系统来释放内存,但这看起来很脏。

You'll be okay if the process is exiting

  

不要担心释放记忆;当进程地址空间被破坏时,它将全部消失。不要担心关闭手柄;当进程句柄表被销毁时,句柄会自动关闭。不要试图调用其他DLL,因为那些其他DLL可能已经收到了他们的DLL_PROCESS_DETACH通知,在这种情况下,如果你试图在析构函数运行后尝试使用它,它们的行为可能与Delphi对象行为不正常的行为不同

确保在实施“无所事事”策略之前阅读整篇文章和评论并了解它。

答案 1 :(得分:2)

如何/何时分配内存?通常,sanest选项是尝试保留某种对称性(构造函数分配,析构函数deallocates。或者在加载DLL时分配的内存,并在卸载DLL时释放)。

在任何情况下,如果您希望在卸载DLL时收到通知,请查看DllMain函数,特别是DLL_PROCESS_DETACH参数。

答案 2 :(得分:1)

当卸载DLL时,调用DllMain function,fdwReason设置为DLL_PROCESS_DETACH。如文档中所述,请确保检查lpvReserved的值,如果为NULL则仅释放空闲内存;你should not free memory if the process is terminating