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

问题描述 投票:1回答:2

我通过使用'k'将堆内存分配给指针变量new,并将其复制到另一个指针变量'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's:0x7fbb56c02ae0 k's:0x7fbb56c02ae0 d's:0x7fbb56c02ae0 k's:0x7fbb56c02ae0

中止陷阱:6

我期待访问'k''d'在我做segment error之后做了delete d,因为我删除了记忆!

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

c++ memory memory-management
2个回答
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
投票

当你delete的东西,你没有破坏记忆,你只是标记为未使用。 (你也可以运行析构函数中包含的清理代码,但这是另一个故事。)内存本身,即物理位和字节,就像以前一样保留在原位。

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

如果在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
© www.soinside.com 2019 - 2024. All rights reserved.