linux C語言 記憶體申請 堆 棧 大小限制
C語言申請記憶體時堆疊大小限制
一直都有一個疑問,一個程序可以使用多大的記憶體空間,swap交換空間以及實體記憶體的大小,ulimit的stack size對程序的記憶體使用有怎樣的限制?今天特親自動手實驗了一次,總結如下:
開闢一片記憶體空間有2種方式,第一種:int a[];第二種malloc,那麼在linux下,這兩種方式可以開闢多大的記憶體空間呢?下面依次進行實驗:
第一種方式:使用malloc申請記憶體;
這樣的方式是在堆區申請的記憶體,在linux中,其實是在申請的時候基本沒有限制,比如32位機器,理論上可以malloc(4G)的大小,因為2^32=4G,但事實上linux的程序地址空間是這樣的:
所以經過實驗,使用malloc最大能夠申請的空間是3G左右,這裡要注意,要使用下面這樣的方式申請空間:
int MB = 0;
while(malloc(1 << 20))
{
MB++;
}
printf("Allocate %d MB total\n", MB);
不能直接
size_t MB = (size_t)(2147483648UL);
char *buf = (char*)malloc(MB);
因為可能記憶體中存在碎片,記憶體空閒空間總和也許有3G,但是直接申請3G,可能會不成功,因為它不是連續的記憶體空間。
接下來我又迷茫了,為什麼申請堆空間不受到swap空間和實體記憶體大小的限制呢?由於linux使用的是虛擬記憶體,因此分配是不受影響的,但是,在使用的時候,我們同時使用的記憶體大小超過了swap空間和實體記憶體大小,將會出現一些問題,這裡有一篇文章說得不錯,記錄下:
第二種方式:使用int a[]申請記憶體;
這樣的方式是在棧區申請的記憶體,在linux中,會受到ulimit -a中stack size結果的影響
比如我的ulimit -a結果
stack size (kbytes, -s) 8192
那麼程式碼中
// int MB[2097152]; 4*2097152 = 8192kb int MB[2090000]; MB[0] = 0; MB[2090000 - 1] = 0;
int MB[2097152];
使用int MB[2097152]會失敗,因為堆疊可能儲存引數,返回地址等等資訊,已經佔用了部分堆疊,下面的MB[2090000]是可以成功的!
所以總結一下:如果用malloc的方式,一個程序理論上是可以使用3G的記憶體(應該說可見),但是同時能夠使用的真正最大記憶體只有swap空間+物理空間這麼大
使用int a[]這樣的形式,申請的空間會受到ulimit -a中stack size的影響。
ps:其實我覺得堆疊就不應該一起說~他倆的概念還是差很多的~我搜到的文章都把這兩者混在一起說,非常容易迷惑人.....
記錄下參考的文章: