我正在尝试创建一个简单的Win32 DLL。作为DLL和EXE之间的接口我使用C函数,但在DLL内部我使用C ++单例对象。以下是我的DLL实现的一个示例:
// MyDLLInterface.cpp文件--------------------
#include "stdafx.h"
#include <memory>
#include "MyDLLInterface.h"
class MySingleton
{
friend class std::auto_ptr< MySingleton >;
static std::auto_ptr< MySingleton > m_pInstance;
MySingleton()
{
m_pName = new char[32];
strcpy(m_pName, “MySingleton”);
}
virtual ~ MySingleton()
{
delete [] m_pName;
}
MySingleton(const MySingleton&);
MySingleton& operator=(const MySingleton&);
public:
static MySingleton* Instance()
{
if (!m_pInstance.get())
m_pInstance.reset(new MySingleton);
return m_pInstance.get();
}
static void Delete()
{
m_pInstance.reset(0);
}
void Function() {}
private:
char* m_pName;
};
std::auto_ptr<MySingleton> MySingleton::m_pInstance(0);
void MyInterfaceFunction()
{
MySingleton::Instance()->Function();
}
void MyInterfaceUninitialize()
{
MySingleton::Delete();
}
// MyDLLInterface.h文件--------------------
#if defined(MY_DLL)
#define MY_DLL_EXPORT __declspec(dllexport)
#else
#define MY_DLL_EXPORT __declspec(dllimport)
#endif
MY_DLL_EXPORT void MyInterfaceFunction();
MY_DLL_EXPORT void MyInterfaceUninitialize();
我遇到的问题或问题如下:如果我不从我的EXE 退出实例()调用 MyInterfaceUninitialize() ,我有内存泄漏( m_pName 指针)。为什么会这样?看起来EXE退出后发生 MySingleton 的破坏。是否可以强制DLL或EXE稍早销毁 MySingleton ,所以我不需要调用 MyInterfaceUninitialize()函数?
修改 感谢您的帮助和解释。现在我明白这是一个设计问题。如果我想继续使用我当前的解决方案,我需要在我的EXE中调用 MyInterfaceUninitialize()函数。如果我不这样做,它也没关系,因为当它离开EXE范围时,单身就会自我毁灭(但我需要忍受令人不安的调试器消息)。避免这种行为的唯一方法是重新考虑整个实现。
我还可以将我的DLL设置为Visual Studio中Linker-&gt; Input下的“Delay Loaded DLLs”,以摆脱令人不安的调试器消息。
答案 0 :(得分:3)
如果我没有从我的EXE ExitInstance()调用MyInterfaceUninitialize(),我有内存泄漏( m_pName 指针)。为什么会这样?
这不是泄漏,这是auto_ptr
应该工作的方式。它们在超出范围时释放实例(在您的情况下是卸载dll的时候)。
看起来,在EXE退出后,MySingleton遭到破坏。
是
是否可以强制DLL或EXE稍早破坏MySingleton,所以我不需要调用MyInterfaceUninitialize()函数?
不是没有调用此函数。
答案 1 :(得分:2)
您可以利用DllMain callback function在加载/卸载DLL或进程/线程附加/分离时采取适当的操作。然后,您可以为每个连接的进程/线程分配对象,而不是使用单例,因为此回调函数在附加线程的上下文中执行。考虑到这一点,还要看看Thread Local Storage (TLS)。
答案 2 :(得分:1)
老实说,对于您提供的示例,如果从ExitInstance调用Uninitialize方法并不重要。是的,调试器会抱怨未释放的内存,但是再次,它是一个单例,它的目的是延长一段时间。
只有在DLL中有一些需要在退出时保留的状态信息,或者如果您多次动态加载/卸载DLL时,您是否需要勤勉地进行清理。否则,只是让操作系统在退出时拆除进程就好了,报告的内存泄漏在这一点上是无关紧要的。