【问题标题】:Passing STL vector wrapped in shared_ptr [duplicate]传递包裹在 shared_ptr 中的 STL 向量 [重复]
【发布时间】:2018-01-11 19:51:34
【问题描述】:

我想知道我试图将向量从 DLL 返回到 .exe 应用程序的情况。 DLL 和 .exe 应用程序的编译器和设置是相同的。我知道在分配/释放内存的情况下,通过 DLL 边界传递 STL 向量可能会导致内存错误。

返回由shared_ptr 包裹的vector 的情况如何?这个内存安全吗?

小例子:

导出的DLL方法:

__declspec(dllexport) std::shared_ptr<std::vector<MyObject>> MyDLL::myMethod()
{
    //Create object
    MyObject obj;
    std::vector<MyObject> myVector;
    myVector.push_back(obj);

    //Create wrapper
    std::shared_ptr<std::vector<MyObject>> spvObject = std::make_shared<std::vector<MyObject>>(myVector);

    return spvObject;
}

在 .exe 端获取此数据:

MyDll dll;
std::shared_ptr<std::vector<MyObject>> objFromDll = dll.myMethod();

当 .exe 应用程序的指针超出范围时会发生什么?从DLL中删除堆会不会出现内存错误?

【问题讨论】:

  • 已编辑,错误见谅。
  • 然后,除了在堆栈上创建临时对象和临时向量之外,鉴于MyObject 具有适当的复制/移动构造函数,并且调用者和 dll 的编译器/设置相同,这段代码就可以了。此外,由于(至少在此代码 sn-p 中)所有权实际上并未共享而是转移,因此使用 unique_ptr 会更好。
  • DLL 是否在内部使用创建的向量?根据示例,您可以按值返回向量。
  • @TaylorHansen,在这种情况下,当来自 .exe 的vector 超出范围时,我的应用程序崩溃了。当我使用 unique_ptr. Only with shared_ptr' 时也会发生同样的情况。
  • 那么MyObject 类很可能有问题,很可能缺少/错误的构造函数和赋值运算符。

标签: c++ vector dll stl shared-ptr


【解决方案1】:

只要 EXE 和 DLL 就使用的分配器达成一致,通过边界传递对象就可以了,但是这是一个非常大的“如果”。例如,如果使用新的编译器版本重新构建 EXE 但不重新构建 DLL,则会违反此规定。

shared_ptr 并没有真正改变这一点,它只是确保对象在不再被引用时将被删除,它与实际使用的分配器无关。

【讨论】:

    【解决方案2】:

    好吧,std::shared_ptr 本身是安全的,因为它在其分配器上使用了类型擦除。

    不安全的是它拥有的std::vector,因为它直接使用std::allocator,除非您的EXE 和您的DLL 同意后者的定义,例如因为它们使用相同的共享运行时库。
    std::shared_ptr 包裹它并没有真正改变任何东西。

    【讨论】:

      【解决方案3】:

      std::shared_ptr 构造函数可以接受'Deleter',它将被存储在控制块内。 也许 DLL 中适当的删除器函数将有助于 EXE/DLL 边界?

      顺便说一句:std::vector 可以使用自定义分配器,也可以自定义为在 dll 或 exe 地址空间中工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-18
        • 1970-01-01
        • 2013-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-04
        相关资源
        最近更新 更多