我通过使用'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's:0x7fbb56c02ae0 d's:0x7fbb56c02ae0 k's:0x7fbb56c02ae0
中止陷阱:6
我期待访问'k'
和'd'
在我做segment error
之后做了delete d
,因为我删除了记忆!
我错过了什么,有人可以帮助我吗?
然而,当我做
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
当你delete
的东西,你没有破坏记忆,你只是标记为未使用。 (你也可以运行析构函数中包含的清理代码,但这是另一个故事。)内存本身,即物理位和字节,就像以前一样保留在原位。
因此,当你delete
指针时,指针在事后仍然指向物理内存中的相同字节,但不允许再使用它们。如果你这样做,任何事都可以发生。这甚至适用于指针本身:任何指向delete
d内存的指针都不能再被触摸,它立即无效。
如果在delete
d之后使用指针,它可能看起来工作正常。或者你可能会崩溃。或者,您可以访问使用相同物理字节的内存创建的其他内存对象。你根本不知道实际会发生什么。
因此,你最初的想法是正确的:只有两个指针中只有一个需要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