当每个两个指针都位于相同的内存中时,为什么必须调用两次“删除”?

时间:2019-04-25 08:28:09

标签: c++ memory memory-management

我使用'k'将堆内存分配给了指针变量new,并将其复制到另一个指针变量'd'中。

在那种情况下,我认为这两个变量指向同一个内存,因此"delete"仅在一个变量中需要内存; 'k''d'。但是,当我执行delete k时,'k''d'指向了内存。

所以我做了delete d,然后出现了Abort trap 6 error

这是我的测试代码。

int* k;
k = new int(5);

int* d = k;

cout<<"d's : "<<d<<endl;
cout<<"k's : "<<k<<endl;

delete d;

cout<<"d's : "<<d<<endl;
cout<<"k's : "<<k<<endl;

delete k;

cout<<"d's : "<<d<<endl;
cout<<"k's : "<<k<<endl;

结果是

  

d's:0x7fbb56c02ae0
  k:0x7fbb56c02ae0
  d's:0x7fbb56c02ae0
  k:0x7fbb56c02ae0

     

中止陷阱:6

我希望访问'k''d'在完成segment error之后就成为delete d,因为我删除了内存!

我想念的是什么,有人可以帮我吗?

2 个答案:

答案 0 :(得分:3)

  

但是,当我做delete k时,kd指向了内存。

在某个指针上调用operator delete会要求操作系统释放与此指针关联的内存,但不会更改指针本身的值。 kd只是继续指向内存中的同一位置,同时释放该内存。

这就是为什么有时人们在nullptr插入之后设置指向delete的指针的原因。就您而言,这将使您摆脱不确定的行为:

delete d;

d = nullptr;
k = nullptr; // Both must be re-assigned

delete k; // Ok, delete on a nullptr is a no-op

答案 1 :(得分:1)

当您delete进行某项操作时,您并不是在销毁内存,而是将其标记为未使用。 (您也可以运行析构函数中包含的清理代码,但这是另一回事。)内存本身(即物理位和字节)与以前一样保留在原处。

这样,当您delete指针时,事实后,该指针仍指向物理内存中的相同字节,但是您不再被允许使用它们。如果这样做,则允许发生任何事情。这甚至适用于指针本身:不能再触摸指向delete d内存的任何指针,它立即无效。

如果delete之后确实使用了指针,则可能似乎可以正常工作。否则,您可能崩溃。或者,您可以访问使用相同物理字节内存创建的其他一些内存对象。 您根本不知道会发生什么

这样,您的最初想法是正确的:只有两个指针之一恰好需要delete,事实发生后,绝对不能触摸两个指针中的另一个:

int* k;
k = new int(5);

int* d = k;

cout<<"d's : "<<d<<endl;
cout<<"k's : "<<k<<endl;

delete d;

// cout<<"d's : "<<d<<endl;    //Undefined behavior, the pointer is invalid now
// cout<<"k's : "<<k<<endl;    //Undefined behavior, k is invalid as well

// delete k;    //Undefined behavior, k is invalid