这可能是一个非常简单的问题,但请帮助我。
我想知道当我打电话给new&删除,例如在下面的代码中
char * ptr=new char [10];
delete [] ptr;
调用new返回我的内存地址。它是否在堆上分配了精确的10个字节,其中存储了有关大小的信息。当我在同一个指针上调用delete时,我在调试器中看到在10个字节之前和之后有很多字节被更改。
每个新的是否有任何标题,其中包含有关new分配的字节数的信息。
非常感谢
答案 0 :(得分:13)
是否分配精确的10个字节
这依赖于实现。保证是“至少 10个字符”。
存储有关大小的信息?
这取决于实现。
每个新的是否有任何标题包含有关新分配的字节数的信息?
这取决于实现。
“依赖于实现”我的意思是它没有在标准中定义。
答案 1 :(得分:5)
这完全取决于编译器和运行时库。它只是精确定义了new
和delete
对您的程序产生的影响,但未指定这些影响的确切程度。
在您的情况下,似乎分配了比请求更多的内存,它可能存储管理信息,如当前内存块的大小,有关可用空间的相邻区域的信息或帮助调试器尝试检测的信息缓冲区溢出和类似的问题。
答案 2 :(得分:3)
完全依赖于实现。一般情况下,您必须在其他地方存储元素的数量。实现必须为至少指定的元素数量分配足够的空间,但它可以分配更多。
答案 3 :(得分:3)
每个新的是否有任何标题,其中包含有关new分配的字节数的信息。
这取决于平台,但是,在很多平台上都有。
答案 4 :(得分:2)
准确地说,根据标准,new char[10]
将在堆中分配至少 10个字节。
new
和delete
的内部依赖于实现。所以它会因编译器和平台而异。此外,您可以找到各种分配器算法(例如:TCMalloc)。
我会概述 在内部如何工作,但不要把它当作绝对真理。它的编写仅用于解释。
简而言之,new
运算符在内部调用malloc
。 malloc
使用了一个非常长的可用内存块列表,即free chain
。调用malloc
时,它会查找此列表以查找足以容纳所请求大小的第一个块。之后,它将块分成两部分,一部分是您请求的大小,另一部分是其余部分,然后将其添加回自由链。最后,它返回具有请求大小的块。
反向发生在free
调用中,由delete / delete []调用。简而言之,它将提供的块放回free chain
。
在我上面描述的过程中可能会有花哨的技巧,比如排序free chain
,将请求的大小四舍五入到下一个2的幂,以减少内存碎片,等等。
答案 5 :(得分:0)
char * ptr=new char [10];
你正在堆中创建一个包含10个字符的数组,并在指针中存储第0个元素的地址。这类似于在C中执行malloc
delete [] ptr;
你正在删除(释放内存)由早期语句分配的堆内存。这类似于在c中免费执行。
答案 6 :(得分:0)
它依赖于实现,但是大多数内存块的元数据通常存储在返回内存地址之前的区域中。您在10个字节之前观察到的更改可能是为此块更新了元数据(可能是正在写入元数据的块的大小),并且在10个字节之后是为下一个块更新的元数据(仍然未分配,可能指向空闲列表中下一个块的指针。)
混乱堆不是一个好主意,因为它不可移植。但是,如果你想做这样的堆魔术,我建议你实现自己的内存池(只需从堆中获取大量内存并自行管理)。一个可能的起点是查看libmm。
答案 7 :(得分:0)
虽然细节是依赖于实现的,但实现需要存储的一条信息是数组中元素的数量。或者,如果它不直接存储它,则需要从分配的块大小中准确地导出它。
原因是因为如果使用new []分配了一个对象数组,当使用delete []删除它们时,需要调用数组中每个对象的析构函数。 delete []需要知道要销毁多少个对象。这就是为什么有必要将new与delete和new []与delete []匹配。