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

C++11 当来自shared_ptr get()的原始指针被删除时会发生什么情况?,c++11,shared-ptr,undefined-behavior,delete-operator,C++11,Shared Ptr,Undefined Behavior,Delete Operator,我编写了如下代码: shared_ptr<int> r = make_shared<int>(); int *ar = r.get(); delete ar; // report double free or corruption // still some code shared_ptr r=make_shared(); int*ar=r.get(); 删除应收账款;//举报双重贪污 //还有一些代码 当代码运行到删除ar时,程序崩溃并报告​ “双重自由还是腐败”

我编写了如下代码:

shared_ptr<int> r = make_shared<int>();
int *ar = r.get();

delete ar; // report double free or corruption
// still some code
shared_ptr r=make_shared();
int*ar=r.get();
删除应收账款;//举报双重贪污
//还有一些代码
当代码运行到
删除ar时,程序崩溃并报告​ “双重自由还是腐败”,我很困惑为什么双重自由?“r”仍然在范围内,并且没有从堆栈中弹出。delete操作符做了什么神奇的事情吗??它是否知道原始指针当前由智能指针处理?然后“r”中的计数器会自动递减为零吗?
我知道不建议进行这些操作,但我想知道为什么?

看见我引述:

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

  • 拥有该对象的最后剩余共享_ptr被销毁
  • 拥有该对象的最后一个剩余共享_ptr通过operator=或reset()被分配另一个指针
使用delete表达式或在构造期间提供给shared_ptr的自定义deleter销毁该对象

因此,指针被
shared\u ptr
删除。您不应该自己删除存储的指针

更新:

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

我读了更多的书,标准并没有对
get()
的行为做太多的说明,但我引用了以下内容:

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

因此,似乎允许
get()
返回的指针不一定是
共享的\u ptr
分配的相同指针(可能使用
new
)。因此
delete
该指针是未定义的行为。我将进一步了解细节

更新2:

该标准在§20.7.2.2.6(关于
共享
):

6备注:鼓励但不要求执行多个内存分配。[注:这提供了相当于侵入式智能指针的效率。-结束注]

7[注:这些函数通常会分配比sizeof(T)更多的内存,以允许内部记账结构,如参考计数。-结束注]

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

看见我引述:

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

  • 拥有该对象的最后剩余共享_ptr被销毁
  • 拥有该对象的最后一个剩余共享_ptr通过operator=或reset()被分配另一个指针
使用delete表达式或在构造期间提供给shared_ptr的自定义deleter销毁该对象

因此,指针被
shared\u ptr
删除。您不应该自己删除存储的指针

更新:

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

我读了更多的书,标准并没有对
get()
的行为做太多的说明,但我引用了以下内容:

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

因此,似乎允许
get()
返回的指针不一定是
共享的\u ptr
分配的相同指针(可能使用
new
)。因此
delete
该指针是未定义的行为。我将进一步了解细节

更新2:

该标准在§20.7.2.2.6(关于
共享
):

6备注:鼓励但不要求执行多个内存分配。[注:这提供了相当于侵入式智能指针的效率。-结束注]

7[注:这些函数通常会分配比sizeof(T)更多的内存,以允许内部记账结构,如参考计数。-结束注]


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

您删除的指针不是来自
new
,因此您有未定义的行为(任何事情都可能发生)

参考资料来源:

对于第一种(非数组)形式,表达式必须是指向对象类型的指针或上下文中可隐式转换为该指针的类类型,
shared_ptr<int> r = make_shared<int>();
f (smart_owning<T>(new T), smart_owning<U>(new U));
T *temp1 = new T;
U *temp2 = new U;
auto &&temp3 = smart_owning<T>(temp1);
auto &&temp4 = smart_owning<U>(temp2);
auto &&temp_t = smart_owning<T>(new T);
auto &&temp_u = smart_owning<U>(new U);
f (temp_t, temp_u);
class C { 
public:
  ~C();
};
shared_ptr<C> r = make_shared<C>();
C *ar = r.get();
ar->~C();
pause(); // stops the program forever
|           block requested from allocator          |
| shared_ptr control block |         X object       |
#1                         #2                       #3