舊的malloc()
使用UNIX的實現sbrk()
/brk()
系統調用。但是現在,實施使用mmap()
和sbrk()
。該malloc()
執行的glibc的(這可能是你在你的Ubuntu 14.04使用的)同時使用sbrk()
和mmap()
而選擇使用哪一個,當你要求通常取決於分配請求的大小,這glibc的動態不分配。
對於小分配,glibc使用sbrk()
,對於較大的分配,它使用mmap()
。宏M_MMAP_THRESHOLD
用於決定這一點。目前,它的默認值是set to 128K。這就解釋了爲什麼你的代碼設法分配135152字節,因爲它大約是128K。儘管您只需要1個字節,但您的實施將分配128K用於有效的內存分配。所以在你超過這個限制之前,segfault纔會發生。
您可以通過使用mallopt()
通過更改默認參數與M_MAP_THRESHOLD
玩。
M_MMAP_THRESHOLD
對於由M_MMAP_THRESHOLD分配大於或等於(以字節爲單位)指定的限制 無法滿足從 空閒列表,存儲器分配函數採用MMAP(2)而不是使用sbrk(2)增加程序中斷的 。
使用mmap(2)分配內存具有顯着的優點,即分配的內存塊總是可以獨立地被釋放回 到系統。 (相比之下,只有在頂端釋放內存 時才能修剪堆棧)。另一方面,使用mmap(2)存在一些缺點:在釋放列表上未放置釋放空間 供以後的分配重用;內存可能浪費 ,因爲mmap(2)分配必須是頁面對齊的;並且內核必須執行通過 mmap(2)清零內存的昂貴任務。平衡這些因素導致M_MMAP_THRESHOLD參數的默認設置爲 128 * 1024。
此參數的下限是0。上限是 DEFAULT_MMAP_THRESHOLD_MAX:512 * 1024在32位系統或 4 * 1024 * 1024 *的sizeof在64位系統(長)。
注意:現在,glibc默認使用動態mmap閾值。 閾值的初始值爲128 * 1024,但當塊 大於當前閾值且小於或等於 時釋放DEFAULT_MMAP_THRESHOLD_MAX,則向上調整閾值 至釋放塊的大小。當動態閾值生效時,修剪堆的閾值也是動態調整爲動態mmap閾值的兩倍的 。如果設置了參數M_TRIM_THRESHOLD,M_TOP_PAD,M_MMAP_THRESHOLD或M_MMAP_MAX 中的任意一個,則將禁用對mmap閾值的調整。
例如,如果你這樣做:
#include<malloc.h>
mallopt(M_MMAP_THRESHOLD, 0);
調用malloc()
之前,你可能會看到不同的限制。其中大多數是實現細節,C標準說它是undefined behaviour來寫入你的進程不擁有的內存。因此,要冒你的風險 - 否則,demons may fly out of your nose ;-)
你正在使用什麼操作系統和體系結構? 另外,你確定malloc()調用sbrk()嗎? – Crashworks
我不確定,但我的教授和一些在線資源告訴我。我在ubuntu 14.04 –
ITYM 4096下使用x86架構,而不是4086.「(1)」是什麼? 'sbrk'是一個系統調用(2),'malloc'是一個庫函數(3)。 –