为什么当我在同一内存中各有两个指针时,我必须调用"delete"两次?



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

在这种情况下,我认为这两个变量指向相同的内存,因此"delete"只需要一个变量中的内存;无论'k''d'。然而,当我delete k时,'k''d'指向记忆。

所以我做了delete dAbort 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的 : 0x7fbb56c02ae0 k的 : 0x7fbb56c02ae0 d的 : 0x7fbb56c02ae0

k的 : 0x7fbb56c02ae0


中止陷阱:6

我期望访问'k''d'在我做delete d之后进行segment error,因为我删除了内存!

我错过了什么,有人可以帮助我吗?

然而,当我做delete k时,kd指向记忆。

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

这就是为什么有时人们在delete后设置指向nullptr的指针。在您的情况下,这将使您免于未定义的行为:

delete d;
d = nullptr;
k = nullptr; // Both must be re-assigned
delete k; // Ok, delete on a nullptr is a no-op

当你delete某件事时,你并没有破坏内存,你只是把它标记为未使用。(您也可以运行析构函数中包含的清理代码,但那是另一回事了。内存本身,即物理位和字节,像以前一样保留在原位。

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

如果在指针deleted 后确实使用了指针,则它可能看起来工作正常。或者你可能会崩溃。或者,您可以访问使用相同物理内存字节创建的其他内存对象。你根本不知道实际会发生什么

因此,您最初的想法是正确的:只有两个指针中的一个需要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

相关内容

最新更新