我使用'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
,因为我删除了内存!
我想念的是什么,有人可以帮我吗?
答案 0 :(得分:3)
但是,当我做
delete k
时,k
和d
指向了内存。
在某个指针上调用operator delete
会要求操作系统释放与此指针关联的内存,但不会更改指针本身的值。 k
和d
只是继续指向内存中的同一位置,同时释放该内存。
这就是为什么有时人们在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