正确使用shared_ptr来消除跨DLL边界的释放

Correct use of shared_ptr to eliminate deallocation across DLL boundaries

本文关键字:DLL 边界 释放 shared ptr      更新时间:2023-10-16

我正在阅读"在dll接口中使用shared_ptr "。在那篇文章中,phlipsy在他的回答的最后提出了一种方法,可以跨DLL边界传递没有实现特定对象的方法。基本上,这个想法是从DLL返回一个原始指针,并在EXE中初始化shared_ptr

我认为这是不对的。为了简单起见,让我重新设计一下。

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

我说的对吗?

你说的都对。第二种正确的方法是通过createObject(..)返回一个原始指针,用它初始化一个shared_ptr,并向shared_ptr传递一个自定义删除器。自定义删除器是一个库函数,如releaseObject(..)。

编辑:使用您的版本(createObject(..)返回shared_ptr<.>),您将绑定到库和库用户的特定shared_ptr实现。

一般规则是分配/释放内存应该始终从相同的模块完成。因此,您可以创建一个与分配器共享的指针,该分配器在分配模块中调用正确的分配方法。

适用于原始指针的规则仍然适用,即使您将它们包装在智能指针中。