简体   繁体   English

销毁DLL中的单例

[英]Destruction of singleton in DLL

I'm trying to create a simple Win32 DLL. 我正在尝试创建一个简单的Win32 DLL。 As interface between DLL and EXE I use C functions, but inside of DLL i use C++ singleton object. 作为DLL和EXE之间的接口,我使用C函数,但在DLL内部,我使用C ++单例对象。 Following is an example of my DLL implementation: 以下是我的DLL实现的示例:

// MyDLLInterface.cpp file -------------------- // 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 file -------------------- // 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();

The problem or the question that i have is following: If i don't call MyInterfaceUninitialize() from my EXEs ExitInstance() , i have a memory leak ( m_pName pointer). 我遇到的问题是:如果我从EXE的ExitInstance()调用MyInterfaceUninitialize()则会发生内存泄漏( m_pName指针)。 Why does it happening? 为什么会发生? It looks like the destruction off MySingleton happens after EXEs exit. 看起来,EXE退出后, MySingleton的破坏就发生了。 Is it possible to force the DLL or EXE to destroy the MySingleton a little bit earlier, so I don't need to call MyInterfaceUninitialize() function? 是否有可能迫使DLL或EXE提前破坏MySingleton ,所以我不需要调用MyInterfaceUninitialize()函数?

EDIT: Thanks for all your help and explanation. 编辑:感谢您的所有帮助和解释。 Now i understand that this is a design issue. 现在我知道这是一个设计问题。 If i want to stay with my current solution, i need to call MyInterfaceUninitialize() function in my EXE. 如果我想保留当前的解决方案,则需要在EXE中调用MyInterfaceUninitialize()函数。 If i don't do it, it also OK, because the singleton destroys itself, when it leaves the EXE scope (but i need to live with disturbing debugger messages). 如果我不这样做,那也行,因为当单例离开EXE范围时,它会自毁(但我需要忍受令人不安的调试器消息)。 The only way to avoid this behavior, is to rethink the whole implementation. 避免此行为的唯一方法是重新考虑整个实现。

I can also set my DLL as "Delay Loaded DLLs" under Linker->Input in Visual Studio, to get rid of disturbing debugger messages. 我还可以在Visual Studio的“链接器”->“输入”下将DLL设置为“延迟加载的DLL”,以消除令人讨厌的调试器消息。

If i don't call MyInterfaceUninitialize() from my EXEs ExitInstance(), i have a memory leak ( m_pName pointer). 如果我不从我的EXE ExitInstance()调用MyInterfaceUninitialize(),则发生内存泄漏( m_pName指针)。 Why does it happening? 为什么会发生?

This is not a leak, this is the way auto_ptr s are supposed to work. 这不是泄漏,这是auto_ptr应该工作的方式。 They release the instance when they go out of scope (which in your case is when the dll is unloaded). 他们超出范围时(在您的情况下就是dll卸载时)释放实例。

It looks like the destruction off MySingleton happens after EXEs exit. 看起来,EXE退出后,MySingleton的破坏就发生了。

Yes. 是。

Is it possible to force the DLL or EXE to destroy the MySingleton a little bit earlier, so I don't need to call MyInterfaceUninitialize() function? 是否有可能迫使DLL或EXE提前破坏MySingleton,所以我不需要调用MyInterfaceUninitialize()函数?

Not without calling this function. 并非没有调用此函数。

You can take advantage of the DllMain callback function to take appropriate action when the DLL is loaded/unloaded or a process/thread attaches/detaches. 您可以利用DllMain回调函数在DLL加载/卸载或进程/线程附加/分离时采取适当的措施。 You could then allocate objects per attached process/thread instead of using a singleton since this callback function is executed in the context of the attached thread. 然后,您可以为每个附加的进程/线程分配对象,而不是使用单个实例,因为此回调函数在附加线程的上下文中执行。 With that in mind, also take a look at Thread Local Storage (TLS) . 考虑到这一点,还请看一下线程本地存储(TLS)

Honestly, for the example you gave, it doesn't matter if you call the Uninitialize method from your ExitInstance. 坦白地说,对于您给出的示例,是否从ExitInstance调用Uninitialize方法都没有关系。 Yes, the debugger will complain about the unreleased memory, but then again, it's a singleton, it's intended to live for an extended duration. 是的,调试器会抱怨未释放的内存,但是再说一次,这是一个单例,旨在延长寿命。

Only if you have some state information in the DLL that needs to be persisted at exit, or if you are dynamically loading/unloading DLLs multiple times, do you need to be diligent about cleaning up. 仅当DLL中有一些状态信息需要在退出时保留,或者如果您多次动态加载/卸载DLL时,才需要认真进行清理。 Otherwise, just letting the OS tear down the process at exit is just fine, the reported memory leak is inconsequential at that point. 否则,只需要让OS在退出时拆除进程就可以了,此时报告的内存泄漏是无关紧要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM