内存分配责任

时间:2012-04-24 13:10:22

标签: c++ memory-management operating-system

我一直在考虑这个问题,但尚未找到任何解释。

什么模块决定应该分配多少内存,比如C ++程序?操作系统是否决定编译器的建议? ..linker?

分配的内存中堆栈和堆的比例是多少?

4 个答案:

答案 0 :(得分:3)

对于不同的操作系统,答案是不同的。通常,可执行文件包含主线程所需的堆栈大小,由链接器放在那里,可能会被操作系统设置覆盖。可以通过一种或多种方式配置操作系统设置,可能是每个用户。某些操作系统不需要预先指定堆栈大小,它们可以在使用时添加堆栈,或多或少无限期地(直到达到硬限制或系统耗尽空闲内存)。那些确实需要预先确定大小的那些最初可能只分配地址空间而不是内存,并在堆栈达到目的地时将地址映射到内存。

堆通常不会预先分配,因此没有“堆栈和堆的比例”。分配给进程的总内存可能受到限制,也可能不受限制 - 如果不是,那么它可以达到系统资源允许的最高值,或者32位系统可能受到可用地址空间的限制。

答案 1 :(得分:1)

这不是C ++标准中的那种问题。它是编译器和操作系统相关的。

有关链接器产生的事物的示例,操作系统可以考虑确定程序请求的资源,请参阅:

http://en.wikipedia.org/wiki/Executable_and_Linkable_Format#ELF_file_layout

在某些情况下,有些API专门从操作系统请求资源:

Change stack size for a C++ application in Linux during compilation with GNU compiler

还有一些方法可以告诉操作系统在某些环境中设置配额和限制:

https://stackoverflow.com/questions/4983120/limit-memory-usage-for-a-single-linux-process

Set Windows process (or user) memory limit

如果您想对某个操作系统如何管理资源使用情况进行实证研究,您可以通过流程监视器实用程序更好地了解它,而不是查找文档...尤其是。使用闭源操作系统。

答案 2 :(得分:1)

取决于您的程序和操作系统。通常,在启动时,仅分配足够的内存来保存可执行文件,任何只读数据,通常大约4k用于堆栈。然后,当您调用malloc或new来分配内存时,您将获得虚拟内存空间,而无需任何物理内存备份。这称为延迟分配,只有在您实际写入内存时,内存才会被物理分配。

编译并计算以下内容以了解我在说什么:

//justwrites.c
#include <stdlib.h>

int main(int argc, char **argv) {

int *big = calloc(sizeof(int),19531); // number of writes

return 0;
}

// deadbeef.c
#include <stdlib.h>

int main(int argc, char **argv) {

int *big = malloc(sizeof(int)*20000000); // allocate 8 million bytes
// immediately write to each page to simulate all at once allocation
// assuming 4k page size on 32bit machine
for ( int* end = big + 20000000; big < end; big+=1024 ) *big = 0xDEADBEEF ;

return 0;
}

// bigmalloc.c 
#include <stdlib.h>

int main(int argc, char **argv) {
int *big = malloc(sizeof(int)*20000000); // allocate 80 million bytes
return 0;
}

答案 3 :(得分:0)

至少对于32位窗口,每个进程都有自己的地址空间副本,2G用户2G内核(由所有进程共享),虚拟内存子系统确保访问同一位置的进程获取适当的数据他们的过程。这是程序如何具有相同的入口点并且多次运行,而不是踩在具有相同可执行文件的其他进程使用的数据上。

应用程序将继续消耗更多的虚拟内存,内核将为该进程分配更多物理内存,直到出现问题,物理内存,交换空间/分页文件。您可以通过系统调用限制进程可以使用的内存。

堆栈和堆几乎总是分配在可用内存的两端,因此堆栈从可用内存的顶部向下增长,而堆从底部开始增长(此决定取决于体系结构)。这允许它们单独增长,以便需要大量堆但不多堆栈的程序可以使用与需要大量堆栈而不是堆很多的程序相同的计划。