关于shared_ptr析构函数中的实现错误的困惑

qbl*_*ble 10 c++ atomic memory-model lock-free c++11

我刚刚看过Herb Sutter的演讲:C++和2012年之后:Herb Sutter - 原子<>武器,2 of 2

他在std :: shared_ptr析构函数的实现中显示了错误:

if( control_block_ptr->refs.fetch_sub(1, memory_order_relaxed ) == 0 )
    delete control_block_ptr; // B
Run Code Online (Sandbox Code Playgroud)

他说,由于memory_order_relaxed,删除可以放在fetch_sub之前.

在1:25:18 - 释放不保持在B线下面,它应该在哪里

怎么可能?在关系之前发生 - 之前/顺序 - 因为它们都在单线程中.我可能错了,但fetch_sub和delete之间也存在一个依赖关系.

如果他是对的,哪些ISO项目支持?

Jon*_*ely 0

赫伯在谈话中表明memory_order_release并非如此memory_order_relaxed,但放松会带来更多问题。

除非delete control_block_ptr访问control_block_ptr->refs(可能不会),否则原子操作不会对删除产生依赖性。删除操作可能不会触及控制块中的任何内存,它可能只是将该指针返回到自由存储分配器。

但我不确定 Herb 是否在谈论编译器在原子操作之前移动删除,或者只是指副作用何时对其他线程可见。

  • 有一个发生在关系之前,但标准说抽象机的可观察结果是对易失性和原子操作的操作,因为“删除control_block_ptr”两者都不是,在没有内存屏障来防止代码移动的情况下,编译器可以移动它在递减之前,你无法观察到差异......除了这里它会导致错误,但编译器不知道这一点。释放操作不会阻止后续操作移至释放操作之前。 (2认同)
  • 好吧,让 fetch-sub 成为非原子的、正常的递减,让我们考虑单线程。编译器如何无条件地将delete移到if之前?怎么能“提前删除”呢?如果“如果”测试失败,它会做什么?它会复活物体吗? (2认同)