2009-12-24 106 views
10

在C++中开发一个返回boost共享指针并将它们用作参数的DLL是否有效?在DLL接口中使用boost :: shared ptr可以吗?

那么,可以导出这样的功能吗?

1.) boost::shared_ptr<Connection> startConnection(); 
2.) void sendToConnection(boost::shared_ptr<Connection> conn, byte* data, int len); 

在特殊:是否跨越DLL边界或引用计数工作会的要求是EXE和DLL使用相同的运行?

其目的是克服对象所有权的问题。因此,当DLL和EXE不再引用它时,该对象被删除。

回答

10

根据斯科特迈耶斯在Effective C++(第3版)中,shared_ptrs在dll边界是安全的。 shared_ptr对象在创建它的dll中保存了一个指向析构函数的指针。

在他的第18项他说书“的 TR1一个特别好的功能:: shared_ptr的是,它会自动使用它的每个指针删除器 以消除另一种潜在的客户错误,”跨DLL问题。“ 当一个对象被创建时使用新的动态链接库(DLL) ,但在不同的DLL中被删除时,此问题会出现。在许多平台上,如交叉DLL新/删除对导致运行时 错误。 tr1 :: shared_ptr避免了这个问题,因为它的默认删除程序 使用从创建tr1 :: shared_ptr的相同DLL中删除。“

蒂姆莱斯有一个有趣的窍门,但他提到,他提到here。您需要确保在shared_ptr最终超出范围之前,不会卸载创建shared_ptr的DLL。我会说在大多数情况下,这不是你必须注意的,但是如果你创建的是松散耦合的dll,那么我建议不要使用shared_ptr。

另一个潜在的缺点是确保双方都使用兼容版本的boost库创建。 Boost的shared_ptr已经稳定很长一段时间了。至少从1.34开始,它就是tr1兼容的。

+2

请注意:如果您正在连接静态CRT,您将遇到问题。静态链接到CRT的每个模块都有自己的堆。如果所有模块链接到DLL CRT,那么它们将共享一个堆。 – Zac 2013-12-03 07:31:48

2

DLL通常不拥有资源 - 资源由使用DLL的进程拥有。您可能最好返回一个普通指针,然后将其存储在调用端的共享指针中。但没有更多信息,很难100%确定这一点。

4

在我看来,如果它不在标准中,它不是你的库提供的对象/机制,那么它不应该是库的接口的一部分。您可以创建自己的对象来执行引用计数,也可以在下面使用boost,但不应该在接口中显式公开。

2

如果你暴露了一个dll界面的原始指针,那么可以寻找一些东西。它迫使你使用共享的dll CRT,在一个CRT中分配的内存不能在另一个CRT中解除分配。如果你在你所有的模块中使用共享的dll CRT(dll的& exe),那么你很好,它们都共享相同的堆,如果你不穿过CRT,世界将崩溃。

除了这个问题,我同意接受的答案。创建工厂可能不应该为客户端代码定义所有权生命周期管理&。

+0

如何确保exe和dll使用共享的dll CRT?这是什么编译器标志? – 2015-10-31 16:32:01

0

不,它不是。

boost::shared_ptr<T>的布局可能在DLL边界两侧不一样。 (布局受编译器版本,打包编译指示以及其他编译器选项以及Boost源代码的实际版本的影响。)

只有“标准布局”(C++ 11中的新概念,与旧的“POD =普通旧数据”概念)类型可以安全地在分别构建的模块之间传递。

相关问题