有没有办法在libstdc ++中创建原子shared_ptr?

时间:2015-02-26 08:54:29

标签: c++ multithreading c++11 gcc atomic

我需要在我的代码中使用原子shared_ptr - 我有单读者多编写器场景,其中一个小数据结构将被多个线程复制和覆盖。

在看到thisthis(以及我自己的测试)之后,似乎自由原子功能在GCC 4.9.2中仍无效。

我试过简单地将shared_ptr放在原子中:

#include <atomic>
#include <iostream>
#include <memory>

std::atomic<std::shared_ptr<std::string> > a_var;

void place() {
  std::shared_ptr<std::string> ptr1(new std::string("abc"));
  a_var.store(ptr1);
}

int main(int argc, const char *argv[]) {
  place();
  std::shared_ptr<std::string> ptr2 = a_var.load();
  std::cout<< *ptr2 << std::endl;
  return 0;
}

但是在使用g++ --std=c++11 -g <filename> -latomic进行编译后,它会引发段错误。

似乎正在发生的事情是,在调用store之后,使用复制构造函数创建了新的shared_ptr,但它立即被删除,并且在退出place ptr1之后被释放,因此{{ 1}}抛出。

任何想法如何使其发挥作用

2 个答案:

答案 0 :(得分:4)

std::atomic<.>只能用于“平凡的可复制类型”。

std::shared_ptr<std::string>显然不符合这些标准。某处atomic将对象复制为一块内存并违反一个或多个类的某些不变量。

例如我们都知道:

std::shared_ptr<std::string> s(new std::string("abc"));
std::shared_ptr<std::string> t;
memcpy(&t,&s,sizeof(std::shared_ptr<std::string>));

复制结束时是否可编译和可执行。它也是灾难的保证配方。

在你的情况下ptr1没有“知道”它已被复制,所以当它(ptr1)超出范围时它会删除字符串。然后你访问字符串。的动臂。游戏结束。

实现目标的标准方法是使用share_ptr保护std::mutex。没有简单的方法来提供指向字符串的无锁指针。这样的对象将迎来计算革命。

答案 1 :(得分:2)

暂时忘掉C ++ 11闪亮的玩具,看看你真正想要实现的目标。

这里要保护的是你的数据结构,而不是引用它的指针。

我假设“自由原子功能”你的意思是无锁。有一个很好的理由为什么编译器不会让你过于自由地抛出原子。这是因为除了最罕见的情况之外,在除了使用普通旧的阻塞同步之外,效率较低。

C ++ 11使用原子变量玩弄时尚的最新奇思妙想,但是虽然这些东西被包裹成一层漂亮的语法糖,但它的血腥危险并且当被任何人使用时会导致设计不稳定和/或效率低下经验丰富的专家。

在C ++ 14中,你将拥有atomic_shared_pointer,这需要自定义代码,当然不能仅仅通过将共享指针包装到原子模板中来实现,但无论如何这都无法解决你的问题也是。