Правильное использование shared_ptr для устранения освобождения через границы DLL - PullRequest
5 голосов
/ 16 октября 2011

Я читаю " Использование shared_ptr в dll-интерфейсах ". В этом посте Флипси предложил способ пропустить объект, не связанный с реализацией, через границы DLL, в конце своего ответа. По сути, идея состоит в том, чтобы вернуть необработанный указатель из DLL и инициализировать shared_ptr в EXE с этим необработанным указателем.

Я не думаю, что это правильно. Позвольте мне перепрототипировать его для простоты.

// wrong version??
// DLL
Object* createObject()
{
  return new Object;
}

// EXE
std::tr1::shared_ptr<Object> p(createObject());
..

Когда object освобождается, контекст / куча уничтожения, используемый shared_ptr, отличается от используемого в DLL во время построения.

Правильный способ использования shared_ptr заключается в том, что распределение ресурсов должно быть в одной строке с инициализацией shared_ptr, чтобы при распределении и освобождении можно было использовать одну и ту же кучу, как показано ниже.

// right version
// DLL
std::tr1::shared_ptr<Object> createObject()
{
  return std::tr1::shared_ptr<Object>(new Object);
}

// EXE
std::tr1::shared_ptr<Object> p(createObject());
..

Я прав?

Ответы [ 2 ]

6 голосов
/ 16 октября 2011

Вы правы с обоими утверждениями. Второй правильный способ - вернуть необработанный указатель с помощью createObject (..), инициализировать с ним shared_ptr и передать пользовательское удаление в shared_ptr. Пользовательский удалитель - это библиотечная функция, такая как releaseObject (..).

Edit: С вашей версией (createObject (..) возвращает shared_ptr <..>) вы привязаны к конкретной реализации shared_ptr библиотеки и пользователя библиотеки. В моем предложенном способе это ограничение исчезло.

1 голос
/ 16 октября 2011

Общее правило состоит в том, что выделение / освобождение памяти всегда должно выполняться из одного и того же модуля.Таким образом, вы можете создать общий указатель с распределителем, который вызывает правильный метод освобождения в модуле выделения.

Правила, которые применяются к необработанным указателям, по-прежнему применяются, даже если вы заключили их в интеллектуальный указатель.

...