c++ - C++ 使用指向 std::shared_ptr 的原始指针
问题描述
所以我试图通过我正在使用的消息传递机制在线程之间传递一个共享指针。由于序列化/反序列化的工作方式,我无法将 shared_ptr 直接嵌入到我发送的消息中。所以我实际上需要发送一个 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 管理的地图中(我试图省略我最初认为不重要的细节)。然而,我没有意识到的是,我从所述地图中检索的方式是不正确的。我将地图的内容复制到临时 shared_ptr 中,然后将临时 shared_ptr 的地址发送到 thread2。所以我无意中发送了堆栈上变量的地址。愚蠢的错误,但我认为这个线程中的评论仍然很有启发性/有帮助。以下似乎解决了我的问题。
auto& objPtr = m_objMap[index];
uint64_t serializedPtr = reinterpret_cast<uint64_t>(&objPtr);
解决方案
shared_ptr
当您复制它时(使用 assignment )自动增加和减少其内部存储的引用计数operator=
,并且 - 重要的是 - 当 ashared_ptr
被销毁时(通过超出范围)。您传输指向共享指针的指针的方法在上面的代码中存在根本缺陷,因为您传输的是临时共享指针的地址,而不是所有权或 lifespan。shared_ptr
仍然由线程 A 拥有的 - 可能会超出范围并在线程 B 可以使用它之前被销毁 。
为了转移 shared_ptr 实例的所有权,我建议创建一个堆分配/动态shared_ptr
的转移。这可以使用new
or (甚至更好)来完成make_unique
。使用 unique_ptr (ie: unique_ptr<shared_ptr<ObjectClass>>
),在将指针传递到消息中的线程屏障之前,您将使用“释放”方法。
线程 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
而不是在 a 中捕获它来进一步缩短此时间unique_ptr<shared_ptr<T>>
,但我个人更喜欢这种方法,因为它对飞行中的指针具有明确的“捕获”和“释放”语义。
推荐阅读
- linq - 使用 Select 到新对象时,Linq 不返回值
- neo4j - neo4j apoc.algo.dijkstra '<' 或 '>' 或 '|' 指标
- python - 如何在python中添加逗号或任何标点符号作为列表元素?
- swift - 通用协议类型参数与直接协议类型的区别
- python - 使用 Spacy 进行 NER 训练
- c# - Visual Studio 2017 社区未正确找到参考
- bash - 当我尝试替换字符串时 sed 给出错误
- sql - SQLITE 多对多关系频率计数
- postgresql - 我可以找到与 PostgreSQL 的某些查询“接近”的文本吗?
- javascript - 对象有值但说大小为 0 javascript