当来自shared_ptr get()的原始指针被删除时会发生什么?

Mic*_* Ma 5 shared-ptr undefined-behavior delete-operator c++11

我写了一些这样的代码:

\n\n
shared_ptr<int> r = make_shared<int>();\nint *ar = r.get();\n\ndelete ar; // report double free or corruption\n// still some code\n
Run Code Online (Sandbox Code Playgroud)\n\n

当代码运行到 时delete ar;,程序崩溃,并报告\xe2\x80\x8b“双重释放或损坏”,我很困惑为什么双重释放?“r”仍然在范围内,并且没有从堆栈中弹出。删除操作符有什么神奇的作用吗?它是否知道原始指针当前由智能指针处理?然后“r”中的计数器自动减为零?\n我知道不推荐操作\xef\xbc\x8c,但我想知道为什么?

\n

Dan*_*iel -2

\n看这里。我引用:

\n\n
\n

std::shared_ptr 是一个智能指针,它通过指针保留对象的共享所有权。多个shared_ptr对象可能拥有同一个对象。当发生以下任一情况时,该对象将被销毁并释放其内存:

\n\n
    \n
  • 拥有该对象的最后剩余的shared_ptr被销毁;
  • \n
  • 拥有该对象的最后一个剩余的shared_ptr通过operator=或reset()分配另一个指针。
  • \n
\n\n

使用delete表达式或在构造期间提供给shared_ptr的自定义删除器来销毁该对象。

\n
\n\n

所以指针被删除了shared_ptr。您不应该自己删除存储的指针\n

\n\n

更新:

\n\n

我没有意识到还有更多的语句,并且指针没有超出范围,对不起。

\n\n

我读了更多内容,标准并没有过多说明 的行为get(),但这里有一个注释,我引用:

\n\n
\n

Shared_ptr 可以共享一个对象的所有权,同时存储指向另一个对象的指针。get() 返回存储的指针,而不是托管指针。

\n
\n\n

所以看起来允许返回的指针get()不一定是由shared_ptr(大概使用new)分配的同一指针。所以delete该指针是未定义的行为。我将进一步研究细节。

\n\n

更新2:

\n\n

标准在 \xc2\xa7 20.7.2.2.6 (大约make_shared)处说:

\n\n
\n

6 备注:鼓励但不要求实现执行不超过一次的内存分配。[注意:这提供了与侵入式智能指针相当的效率。\xe2\x80\x94 尾注]

\n\n

7 [ 注意:这些函数通常会分配比 sizeof(T) 更多的内存,以允许内部簿记结构,例如引用计数。\xe2\x80\x94 尾注]

\n
\n\n

因此,特定的实现make_shared 可以分配单个内存块(或更多)并使用该内存的一部分来初始化存储的指针(但可能不是分配的所有内存)。get()必须返回一个指向存储对象的指针,但正如前面所说,标准没有要求返回的指针get()必须是 分配的指针new。因此delete该指针未定义的行为,您收到了一个信号,但任何事情都可能发生。

\n