gpt4 book ai didi

C++ 使用指向 std::shared_ptr 的原始指针

转载 作者:行者123 更新时间:2023-12-02 05:38:21 26 4
gpt4 key购买 nike

因此,我尝试通过我正在使用的消息传递机制在线程之间传递共享指针。由于序列化/反序列化的工作方式,我无法直接将共享指针嵌入到我发送的消息中。所以我实际上需要发送一个shared_ptr的原始指针。见下文:

主题 1:

auto objPtr = std::make_shared<ObjectClass>();
uint64_t serializedPtr = reinterpret_cast<uint64_t>(&objPtr);

主题 2:

std::shared_ptr<ObjectClass> objPtrT2 = *(reinterpret_cast<std::shared_ptr<ObjectClass>*>(serializedPtr));

当线程 2 增加共享指针的引用计数时,有时会崩溃。我只能假设这里存在一些竞争条件,但无法找到解决方案。请注意,它并不总是崩溃,并且反序列化似乎总是成功。

我是否需要同步对此shared_ptr(shared_ptr本身,而不是share_ptr指向的内容)的访问?我担心我传输此shared_ptr 的方式会破坏引用计数的管理方式。

出于其他与性能相关的原因,我仍在争论使用shared_ptr是否适合,但我想知道为了我自己的利益我做错了什么。

谢谢

编辑:请注意,线程 1 和线程 2 位于同一进程/主机中。我将shared_ptr放入由thread1管理的映射中(我试图省略我最初认为不重要的细节)。然而,我没有意识到我从所述 map 中检索的方式是不正确的。我将映射的内容复制到临时shared_ptr中,然后将临时shared_ptr的地址发送到thread2。所以我无意中发送了堆栈上变量的地址。愚蠢的错误,但我认为该线程中的评论仍然非常有启发性/有帮助。以下内容似乎可以解决我的问题。

auto& objPtr = m_objMap[index];
uint64_t serializedPtr = reinterpret_cast<uint64_t>(&objPtr);

最佳答案

shared_ptr当您复制它时(使用赋值 operator= ),并且 - 重要的是 - 当 shared_ptr 时,它会自动增加和减少其内部存储的引用计数被破坏(超出范围)。上面的代码中传输指向共享指针的指针的方法从根本上来说是有缺陷的,因为您传输的是临时共享指针的地址,而不是所有权或生命周期嗯>。 shared_ptr - 仍然由线程 A 拥有 - 可能会超出范围并在线程 B 可以使用它之前被销毁。

为了转移shared_ptr实例的所有权,我建议创建一个堆分配/动态shared_ptr用于转移。这可以使用 new 来完成或(更好)make_unique 。使用 unique_ptr (即: unique_ptr<shared_ptr<ObjectClass>> ),您可以在将指针传递到消息中的线程屏障之前使用“release”方法。

线程A:

auto sharedPtr = std::make_shared<ObjectClass>();

// This line creates a heap-allocated copy of a
// shared_ptr (incrementing reference count)
// And places ownership inside a unique_ptr
auto sharedPtrDynamicCopy = std::make_unique<decltype(sharedPtr)>(sharedPtr);

// This 'releases' ownership of the heap-allocated shared_ptr,
// returning a raw pointer; it is now a potential
// memory leak!!! It must be 'captured' in Thread B.
auto rawPtrToPass = sharedPtrDynamicCopy.release();

线程B:

// Here, we immediately 'capture' the raw pointer back
// inside a unique_ptr, closing the loop on the potential
// memory leak
auto sharedPtrDynamicCopy = unique_ptr<shared_ptr<ObjectClass>>(rawPtrFromThreadA);

// Now we can make a copy of the shared_ptr, if we like.
// This sharedCopy will live on, even after recvdPtr goes
// out of scope.
auto sharedCopy = *sharedPtrDynamicCopy;

您也许可以通过简单地“新建”原始 shared_ptr 来进一步缩短此时间而不是将其捕获在 unique_ptr<shared_ptr<T>> 中,但我个人更喜欢这种方法,因为它对于飞行中的指针具有明确的“捕获”和“释放”语义。

关于C++ 使用指向 std::shared_ptr 的原始指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60997631/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com