C ++ new / new [],它是如何分配内存的?

时间:2010-12-12 08:49:02

标签: c++ memory-management malloc new-operator ram

我现在想说明这些指令是如何分配内存的。

例如,如果我有代码:

x = new int[5]; 
y = new int[5];

如果分配它们在RAM中的实际外观? 是为2个变量共享为每个变量或块保留的整个块(内存页面或如何调用它 - 在32位上大小为4KB)?

我在任何手册中找不到我的问题的答案。感谢所有回复。

我在维基百科上发现: 页面的内部碎片 流程很少需要使用确切数量的页面。结果,最后一页可能只是部分填满,浪费了一些内存。较大的页面大小明显增加了这种方式浪费内存的可能性,因为更多可能未使用的内存部分被加载到主内存中。较小的页面大小可确保与分配中所需的实际内存量更加匹配。 例如,假设页面大小为1024KB。如果进程分配1025KB,则必须使用两个页面,从而产生1023KB的未使用空间(其中一页完全消耗1024KB,另一页仅消耗1KB)。

这就是我的问题的答案。无论如何,谢谢你们。

3 个答案:

答案 0 :(得分:4)

您未在手册中找到它,因为标准未指定。也就是说,大部分时间x和y将并排(继续cout<< hex <<他们的地址。)

但是标准中没有任何内容强制这样做,所以你不能依赖它。

答案 1 :(得分:4)

典型的分配器实现将首先调用操作系统以获取大量内存,然后为了满足您的请求,它将为您提供一块内存,这称为子分配。如果内存不足,它将从操作系统中获得更多。

分配器必须跟踪它从操作系统获得的所有大块以及它分发给客户端的所有小块。它还必须接受来自客户的阻止。

典型的子分配算法会保留每个大小的返回块列表,称为 freelist ,并始终尝试满足空闲列表的请求,如果空闲列表为空,则仅转到主块。这种特殊的实现技术对于普通程序来说非常快速且非常有效,但是如果请求大小遍布整个地方(这在大多数程序中并不常见),它具有可怕的碎片属性。

像GNU的malloc实现这样的现代分配器很复杂,但是已经建立了数十年的经验,应该被认为是非常好的,因此很少需要编写自己的专用子分配器。

答案 2 :(得分:1)

每个进程都有不同的关联段,这些段在进程地址空间之间划分: 1)文本段::放置代码的位置 2)堆栈段::进程堆栈 3)数据段::这是保留“新”的存储器的地方。除此之外,它还存储初始化和未初始化的静态数据(bss等)。

因此,每当你调用一个新函数(我猜它在内部使用malloc,但新类使处理内存更安全)时,它会在数据段中分配指定的字节数。 当然,您在运行程序时打印的地址是虚拟的,需要转换为物理地址。但这不是我们的头疼,操作系统内存管理单元为我们这样做。