使用 std::atomic 实现无锁结构,Dtor 崩溃

Using std::atomic to implement a lockfree structure, Dtor crashes

本文关键字:结构 Dtor 崩溃 std atomic 实现 使用      更新时间:2023-10-16

我指的是std::atomic的cpp首选项示例,试图为堆栈添加一个Dtor函数:

  #include<atomic>
  template<class T>
  struct node{
      T data;
      node* next;
      node(const T&data):data(data),next(nullptr){}
  };  
  template<class T>
  class stack{
      std::atomic<node<T>*> head;
  public: 
      void push(const T&data)
      {   
      node<T>* new_node=new node<T>(data);
      new_node->next=head.load(std::memory_order_relaxed);
      while(!std::atomic_compare_exchange_weak_explicit(
                  &head,
                  &new_node->next,
                  new_node,
                  std::memory_order_release,
                  std::memory_order_relaxed));
      }   
      ~stack()
      {   
      node<T>* p=head;
      while(p)
      {
          node<T>* next=p->next;
          delete p;                                                         
          p=next;
      }
      }
  };  
  int main() 
  {
      stack<int> s;
      s.push(1);
      s.push(2);
      s.push(3);
      return 0;
  }

当程序执行到 ~stack 时,最后一个删除函数提示崩溃,如下所示:

$ g++ myatomic.cpp -std=c++11
$ ./a.out
*** Error in `./a.out': munmap_chunk(): invalid pointer: 0x0000000000400b00 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x77725)[0x7f07173a2725]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x1a8)[0x7f07173aec18]
./a.out[0x4008f5]
./a.out[0x400829]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f071734b830]
./a.out[0x4006d9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 2506641                            /home/x/cpp/x01/a.out
00601000-00602000 r--p 00001000 08:01 2506641                            /home/x/cpp/x01/a.out
00602000-00603000 rw-p 00002000 08:01 2506641                            /home/x/cpp/x01/a.out
022f6000-02328000 rw-p 00000000 00:00 0                                  [heap]
7f0717022000-7f071712a000 r-xp 00000000 08:01 2102313                    /lib/x86_64-linux-gnu/libm-2.23.so
7f071712a000-7f0717329000 ---p 00108000 08:01 2102313                    /lib/x86_64-linux-gnu/libm-2.23.so
7f0717329000-7f071732a000 r--p 00107000 08:01 2102313                    /lib/x86_64-linux-gnu/libm-2.23.so
7f071732a000-7f071732b000 rw-p 00108000 08:01 2102313                    /lib/x86_64-linux-gnu/libm-2.23.so
7f071732b000-7f07174eb000 r-xp 00000000 08:01 2102243                    /lib/x86_64-linux-gnu/libc-2.23.so
7f07174eb000-7f07176ea000 ---p 001c0000 08:01 2102243                    /lib/x86_64-linux-gnu/libc-2.23.so
7f07176ea000-7f07176ee000 r--p 001bf000 08:01 2102243                    /lib/x86_64-linux-gnu/libc-2.23.so
7f07176ee000-7f07176f0000 rw-p 001c3000 08:01 2102243                    /lib/x86_64-linux-gnu/libc-2.23.so
7f07176f0000-7f07176f4000 rw-p 00000000 00:00 0 
7f07176f4000-7f071770a000 r-xp 00000000 08:01 2102281                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f071770a000-7f0717909000 ---p 00016000 08:01 2102281                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f0717909000-7f071790a000 rw-p 00015000 08:01 2102281                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f071790a000-7f0717a7c000 r-xp 00000000 08:01 1312401                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f0717a7c000-7f0717c7c000 ---p 00172000 08:01 1312401                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f0717c7c000-7f0717c86000 r--p 00172000 08:01 1312401                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f0717c86000-7f0717c88000 rw-p 0017c000 08:01 1312401                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f0717c88000-7f0717c8c000 rw-p 00000000 00:00 0 
7f0717c8c000-7f0717cb2000 r-xp 00000000 08:01 2102215                    /lib/x86_64-linux-gnu/ld-2.23.so
7f0717e8e000-7f0717e93000 rw-p 00000000 00:00 0 
7f0717eae000-7f0717eb1000 rw-p 00000000 00:00 0 
7f0717eb1000-7f0717eb2000 r--p 00025000 08:01 2102215                    /lib/x86_64-linux-gnu/ld-2.23.so
7f0717eb2000-7f0717eb3000 rw-p 00026000 08:01 2102215                    /lib/x86_64-linux-gnu/ld-2.23.so
7f0717eb3000-7f0717eb4000 rw-p 00000000 00:00 0 
7ffec8e19000-7ffec8e3a000 rw-p 00000000 00:00 0                          [stack]
7ffec8edb000-7ffec8edd000 r--p 00000000 00:00 0                          [vvar]
7ffec8edd000-7ffec8edf000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Terminated

我试图gdb它,第三次删除崩溃。我的程序有什么问题吗?谢谢。

stackhead成员永远不会初始化,因此您的程序具有未定义的行为,这恰好表现为指针为非空并且删除了一些垃圾内存。

通过在构造函数中初始化head来解决此问题stack

stack() : head(nullptr){}