繁体   English   中英

C++ 删除一个指针(空闲内存)

[英]C++ delete a pointer (free memory)

考虑以下代码:

int a = 10;
int * b = &a;
int * c = b;
delete b; // equivalent to delete c;

我对最后一行的理解是否正确, delete bdelete c是等效的,并且两者都将释放保存a的内存空间,因此a不再可访问?

你的程序的行为是undefined 只能在使用new分配的内存指针上使用delete 如果你写过

int* b = new int;
*b = 10;
int* c = b;

然后你可以或者delete b; delete c; 释放你的记忆。 不要尝试在delete调用之后取消引用bc ,这样做的行为也是undefined

如果bc指向相同的内存,则删除它们中的任何一个都会释放内存,因此假设是正确的。 a不可访问是不是在这种情况下,正确的,虽然你不指向动态分配的内存,你只能叫delete / delete[]对与创建一些new / new[] 尝试delete / delete[]一个没有用new / new[]分配的指针是未定义的行为,通常会以段错误结束。

令人困惑的部分是您问题的答案

我在最后一行中的理解是否正确,删除 b 和删除 c 是等效的”

是的,它们是等效的,并且这里的其他地方都提到了 UB。

你永远不应该对在堆栈上分配的变量使用 delete,delete 是 new 的对应物。 因此,当不使用 new/alloc 时,不需要删除/释放,一旦超出代码的“范围”(在这种情况下是程序本身),所有内存都被认为是可用的。

这个特定的答案使用堆的特定实现来详细说明在您提出的情况下会发生什么; 然而这很重要,因为其他版本仍然会有类似的问题接近我提供的论点。

答案是“不”,这是因为其他人所说的。 但是,我会更准确一些,因为我认为你实际上并不知道堆栈和堆是什么,所以我会花时间来解释你。

现在首先,关于堆的细节,我所说的一切都是“谎言”。 没有人具体知道您的编译器实现堆的功能。 所以,我只能给我一堆的理解来代替。

新建和删除实际上是两个函数(如果你已经听说过运算符重载,你会理解我的意思)接受指针并修改内存中的数据结构,称为堆。 它是C / C ++程序内存中的四个主要数据结构之一(堆,堆栈,文本和静态空间)。

堆本质上是一个链表,但不是在每个节点中存储数据,而是将数据填入它们之间。 如果您不熟悉链接列表,那么在此上下文中,它是一个位于原始内存中的双组件“数组”。 第二个组件是存储在它前面的块的长度。 第一个组件是它之前的块的长度。 以这种方式很容易找到一个块,因为它只是向下移动列表搜索块。 通常(因为程序甚至不够复杂到需要在单个块内分配2 ^ 31个字节),最左边的位用作表示块是否空闲的真/假值。 因此,free和new只是列表上的操作而且free只需将指针向上移动一个来查看节点并进行适当的更改。 我不会详细介绍,因为那些熟悉双重链表的人应该理解这些操作,如果你不理解,那我就没有必要教你一些你将在更深层次的深度学习的东西。

请记住:您的实现因编译器而异。 这只是一个例子。

另一方面,堆栈是局部变量所在的位置。 它实际上是一个庞大的数组阵列。 数组的中间保存程序执行后应返回的代码中的地址,然后参数位于一侧,而局部变量位于另一侧。 局部变量没有明确的组织意识。 有些编译器可能会检测到一个值在另一个值之前停止使用并且只是共享内存位置(除非你真正偷看内存或扫描堆栈,否则你永远不会注意到)。

如你所见,这两者根本没有意义。 在索引堆栈的指针上自由调用意味着您尝试在堆栈上执行列表操作。 将发生以下两件事之一:

  1. 您的实现检测到内存甚至不在堆中,并且出现错误消息(非法参数异常)。

  2. 实现是“哑”,实际上尝试执行列表操作。 这意味着内存中变量之前的值将被更改,并且可能会更改其他值以尝试将两个空闲块“合并”为一个更大的块。

简单地说:不要那样做。 你可能会在程序中破坏某些东西。 如果你搞砸了回程线怎么办? 接下来你知道,你有一个无限的函数调用循环......你没有写过循环。 非常非常糟糕。

而且当然:

你对堆的确切实现会有很大的不同,不像堆栈不会发生太大变化。

例如,虽然我从未真正看到过这种结构的原始内存的代码或图表,但我听说有堆空间的模型围绕着两个单独的列表来保存释放的块和分配的块。 这不会影响这个问题,因为仍有某种形式的内部簿记处理分配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM