Уничтожение синглтона в DLL - PullRequest
1 голос
/ 29 октября 2009

Я пытаюсь создать простую Win32 DLL. В качестве интерфейса между DLL и EXE я использую функции C, но внутри DLL я использую объект C ++ singleton. Ниже приведен пример моей реализации 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();

Проблема или вопрос, который у меня есть, следующие: Если я не вызов MyInterfaceUninitialize () из моих EXE-файлов ExitInstance () , у меня есть утечка памяти (указатель m_pName ). Почему это происходит? Похоже, что уничтожение MySingleton происходит после выхода EXE. Можно ли заставить DLL или EXE уничтожить MySingleton чуть раньше, поэтому мне не нужно вызывать MyInterfaceUninitialize () функцию?

EDIT: Спасибо за вашу помощь и объяснения. Теперь я понимаю, что это проблема дизайна. Если я хочу остаться с моим текущим решением, мне нужно вызвать функцию MyInterfaceUninitialize () в моем EXE. Если я этого не делаю, это тоже нормально, потому что синглтон уничтожает себя, когда покидает область действия EXE (но мне нужно жить с тревожными сообщениями отладчика). Единственный способ избежать такого поведения - переосмыслить всю реализацию.

Я также могу установить свою DLL как «Delay Loaded DLLs» в Linker-> Input в Visual Studio, чтобы избавиться от тревожных сообщений отладчика.

Ответы [ 3 ]

3 голосов
/ 29 октября 2009

Если я не вызываю MyInterfaceUninitialize () из ExitInstance () моего EXE-файла, у меня возникает утечка памяти (указатель m_pName ). Почему это происходит?

Это не утечка, это способ, которым auto_ptr должны работать. Они освобождают экземпляр, когда выходят из области видимости (что в вашем случае, когда DLL выгружается).

Похоже, что разрушение MySingleton происходит после выхода EXE.

Да.

Можно ли заставить DLL или EXE-файл уничтожить MySingleton немного раньше, поэтому мне не нужно вызывать функцию MyInterfaceUninitialize ()?

Не без вызова этой функции.

2 голосов
/ 29 октября 2009

Вы можете воспользоваться функцией обратного вызова DllMain , чтобы предпринять соответствующие действия, когда DLL загружается / выгружается или процесс / поток присоединяется / отсоединяется. Затем вы могли бы распределять объекты по каждому присоединенному процессу / потоку вместо использования синглтона, поскольку эта функция обратного вызова выполняется в контексте присоединенного потока. Имея это в виду, обратите также внимание на Thread Local Storage (TLS) .

1 голос
/ 29 октября 2009

Честно говоря, для приведенного вами примера не имеет значения, если вы вызываете метод Uninitialize из вашего ExitInstance. Да, отладчик будет жаловаться на невыпущенную память, но опять же, это синглтон, он предназначен для жизни в течение длительного времени.

Только если у вас есть некоторая информация о состоянии в DLL, которую необходимо сохранить при выходе, или если вы динамически загружаете / выгружаете DLL несколько раз, вам нужно быть внимательным в отношении очистки. В противном случае, просто позволить операционной системе прервать процесс на выходе - это нормально, сообщаемая утечка памяти в этот момент несущественна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...