2012-04-24 64 views
1

我一直在想這個問題,但還沒有找到任何解釋。內存分配責任

什麼模塊決定應分配多少內存,比如說C++程序?它是根據編譯器的建議決定的操作系統嗎? ..linker?

在分配的內存中堆棧和堆的比例是多少?

回答

1

這不是C++標準中的問題。它依賴於編譯器和操作系統。

對於這種事情的接頭產生的OS獲取到的因素確定由一個程序所請求的資源的示例,請參閱:

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

也有辦法告訴操作系統設置配額和限制在某些環境:從OS資源

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

Set Windows process (or user) memory limit

如果你想要做的一定OS是如何管理資源的使用情況進行了實證研究,你可能會得到一個更好的感覺與過程監控工具,而不是找文檔... ESP。與一個閉源操作系統。

3

對於不同的操作系統,答案是不同的。通常,可執行文件包含主線程所需的堆棧大小,由鏈接器放在那裏,這可能會被操作系統設置覆蓋。可以按照一種或多種方式配置操作系統設置,可能按用戶進行配置。一些操作系統不需要預先指定堆棧大小,它們可以在使用堆棧時添加堆棧,或多或少無限期地添加堆棧(直到達到硬限制或系統耗盡可用內存)。那些需要預先設置大小的應用程序最初可能只分配地址空間而不是內存,並且在堆棧達到那個位置時將地址映射到內存。

堆通常不在前面分配,所以沒有「堆棧和堆的比率」。分配給進程的總內存可能會受到限制,也可能不會受到限制 - 如果不是,那麼它可以達到系統資源允許的最大值,或者在32位系統上可能受可用地址空間的限制。

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; 
} 
+0

能考慮到的Windows(據我所知)沒有做到這一點樂觀的內存分配被稱爲「典型」? – 2012-04-24 13:33:28

+0

@Steve:MSVC++沒有。 Windows不支持的Linux/libc的'malloc'用途(即'CreateFileMapping'沒有文件句柄,並沒有特殊的選項)和其他Windows編譯器肯定可以實現'malloc'這樣相同的基本方法。 – MSalters 2012-04-24 14:35:14

+0

@MSalters:真實的,但如果你沒有一個OOM殺手則該技術也不是那麼好。您可能不希望編譯器將OOM殺手的用戶模式版本粘貼到每個應用程序中。 Windows編譯器(包括mingw)實際上是否樂觀地分配,如果是,那麼成功了嗎? – 2012-04-24 14:59:51

0

至少在32位Windows中,每個進程都有自己的地址空間的副本,2G用戶2G內核(由所有進程共享)時,虛擬內存子系統確保訪問相同位置的進程爲其進程獲取適當的數據。這就是程序如何具有相同的入口點並且可以多次運行,而不會使用具有相同可執行文件的其他進程使用的數據。

應用程序將繼續使用更多的虛擬內存,內核會分配更多的物理內存這一進程,直到東西用完,物理內存,交換空間/分頁文件。您可以通過系統調用來限制進程可以使用的內存。

棧和堆幾乎總是分配可用的存儲器的相對端,因此而堆從下向上生長(此決定取決於架構)堆棧從可用存儲器的頂部向下增長。這使得它們可以分別增長,這樣一個需要大量堆但不需要太多堆棧的程序可以使用與需要大量堆棧並且堆不多的相同計劃。