C 程式設計/stdlib.h/malloc
在計算中,malloc 是一個用於執行動態記憶體分配的子程式。malloc 是標準庫的一部分,並在 stdlib.h 標標頭檔案中宣告。
malloc 有許多實現,每種實現的效能都不同,具體取決於計算硬體和程式的編寫方式。效能在執行時間和所需記憶體方面都有所不同。使用 malloc 分配的記憶體的指標最終必須傳遞給 free 子程式以釋放記憶體,以避免記憶體洩漏。
C 程式語言以靜態、自動或動態方式管理記憶體。靜態持續時間的變數在主(固定)記憶體中分配,並在程式的整個生命週期中持續存在;自動持續時間的變數在堆疊上分配,並在函式呼叫和返回時出現和消失。對於靜態持續時間和 C99 之前(允許可變長度自動陣列[1])的自動持續時間變數,分配的大小需要是編譯時常量。如果所需大小在執行時才知道(例如,如果從使用者或磁碟檔案讀取任意大小的資料),那麼使用固定大小的資料物件是不夠的。
分配記憶體的生存期也是一個需要考慮的因素。靜態持續時間和自動持續時間記憶體都不適合所有情況。自動分配的資料無法跨多個函式呼叫持續存在,而靜態資料無論是否需要都會在程式的生命週期中持續存在。在許多情況下,程式設計師需要在管理分配記憶體的生存期方面有更大的靈活性。
透過使用動態記憶體分配可以避免這些限制,在動態記憶體分配中,記憶體以更明確(但也更靈活)的方式管理,通常是從堆中分配,堆是為此目的而構建的記憶體區域。在 C 語言中,庫函式 malloc 用於在堆上分配一塊記憶體。程式透過 malloc 返回的指標訪問這塊記憶體。當不再需要記憶體時,將指標傳遞給 free,該函式釋放記憶體以便可用於其他目的。
一些平臺提供庫呼叫,允許從 C 堆疊而不是堆進行執行時動態分配(例如,Unix alloca(),[2] Microsoft Windows CRTL 的 malloca()[3])。當呼叫函式結束時,這部分記憶體會自動釋放。C99 標準的更改減少了對該功能的需求,該標準增加了對塊範圍的可變長度陣列的支援,這些陣列的大小在執行時確定。
malloc 函式是標準 C 中用於分配記憶體的函式之一。它與陣列類似。它的函式原型是
void *malloc(size_t size);
它分配 size 位元組的記憶體。如果分配成功,則返回指向記憶體塊的指標。此指標保證適合對齊到任何型別(包括結構體等),否則返回 NULL 指標。
透過 malloc 分配的記憶體是持久的:它將繼續存在,即使程式離開呼叫分配的範圍,直到程式終止或程式設計師顯式地釋放記憶體。這是透過使用 free 子程式實現的。它的原型是
void free(void *pointer);
它釋放 pointer 指向的記憶體塊。pointer 必須是之前由 malloc、calloc 或 realloc 返回的,並且 pointer 在傳遞給 free 後不能使用。特別是,透過 new 或 new[] 分配的記憶體不應傳遞給 free,並且未來自 malloc(例如堆疊變數)或已釋放的指標不能傳送到 free。對 NULL 指標呼叫 free 是安全的,沒有影響。
建立 10 個 int 物件陣列的標準方法
int array[10];
但是,如果希望動態地分配類似陣列,則可以使用以下程式碼
/* Allocate space for an array with ten elements of type
int. */
int *ptr = (int *) malloc(10 * sizeof(int));
if (ptr == NULL) {
/* Memory could not be allocated, the program should
handle the error here as appropriate. */
} else {
/* Allocation succeeded. Do something. */
free(ptr); /* We are done with the int objects, and
free the associated pointer. */
ptr = NULL; /* The pointed-to-data must not be used again,
unless re-assigned by using malloc
again. */
}
malloc 返回空指標以指示沒有可用記憶體,或發生阻止分配記憶體的其他錯誤。
由於 malloc 呼叫可能因記憶體不足而失敗,因此定義一個在 malloc 失敗時呼叫 malloc 並退出的宏通常很方便。一個可能的宏定義是
if(!(ptr=malloc(sizeof(int))))
{
fprintf(stderr,"Insufficient memory"); /* Prints the necessary error statement. */
exit(EXIT_FAILURE); /* Exits <code>malloc</code> as there is insufficient memory. */
}
為該宏給出的宏將是
#define MALLOC(p,s) /*Here p & s are 2 integer pointer & variable respectively. */ \
if(!((p)=malloc(s))) \
{ \
fprintf(stderr,"Insufficient memory"); /* Prints the necessary error statement. */ \
exit(EXIT_FAILURE); /* Exits <code>malloc</code> as there is insufficient memory. */ \
}
因此,上面的基本程式碼可以用一行替換
MALLOC(ptr,sizeof(int));
此示例顯示了 malloc 的一個有用習慣用法
int *ptr = malloc(10 * sizeof(*ptr));
也就是說,不要將硬編碼型別寫入 malloc 的引數中,而是使用要分配指標內容的 sizeof 運算子。這可以確保分配左側和右側的型別在程式碼修改時永遠不會不同步。
'C' 函式用於建立和返回大小為 m*n 的二維陣列
int **create(int m, n)
{
int **p, i;
p = (int **)malloc(m*sizeof(int*));/* this will store base order of all the row in p */
for(i = 0; i < m; i++)
p[i] = (int *)malloc(n*sizeof(int));/* this will create m row of n elements */
return p;
}
malloc 返回一個 void 指標 (void *),它表示它是一個指向未知資料型別的區域的指標。malloc 返回的特定指標型別缺乏是型別不安全的行為:malloc 根據位元組數分配,而不是根據型別分配。這與 C++ 的 new 運算子不同,new 運算子返回的指標的型別取決於運算元。(參見 C 型別安全)。
可以將此指標“強制轉換”(參見型別轉換)為特定型別
int *ptr;
ptr = malloc(10 * sizeof(*ptr)); // Without a cast
ptr = (int*)malloc(10 * sizeof(int)); // With a cast
執行此類強制轉換有優點和缺點。
- 包含強制轉換可以與 C++ 相容,C++ 要求進行強制轉換。
- 如果強制轉換存在,並且隨後更改了左側指標的型別,則會生成一個警告,以幫助程式設計師糾正否則可能出現錯誤的行為。
- 強制轉換允許使用最初返回
char *的舊版本malloc。[4]
- 在 ANSI C 標準下,強制轉換是多餘的。
- 新增強制轉換可能會掩蓋未包含標頭檔案
stdlib.h的錯誤,該檔案中包含malloc的原型。[4][5] 在沒有malloc的原型的情況下,標準要求C編譯器假設malloc返回一個int。如果沒有強制轉換,當將該整數賦值給指標時會發出警告;但是,使用強制轉換後,不會產生此警告,從而隱藏了錯誤。在某些架構和資料模型(例如 64 位系統上的 LP64,其中long和指標為 64 位,而int為 32 位)上,此錯誤實際上會導致未定義行為,因為隱式宣告的malloc返回一個 32 位值,而實際定義的函式返回一個 64 位值。根據呼叫約定和記憶體佈局,這可能會導致堆疊溢位。此問題在現代編譯器中不存在,因為它們一致地生成有關使用未宣告函式的警告,因此仍然會出現警告。例如,gcc 的預設行為是顯示一個警告,提示“內建函式的隱式宣告不相容”,無論是否使用強制轉換。
malloc返回一個為程式設計師使用而分配的記憶體塊,但未初始化。如果需要,通常會手動初始化記憶體——可以透過memset函式,或者透過一個或多個取消引用指標的賦值語句。另一種方法是使用calloc函式,該函式分配連續記憶體,然後將其初始化為零。其原型為
void *calloc(size_t nelements, size_t elementSize);
這將分配一個大小為nelements × elementSize的記憶體區域,並將其初始化為 0。當分配一個字元陣列來儲存字串時,這很有用,如下面的示例所示
char *word = calloc(200, sizeof(char));
能夠縮小或擴大記憶體塊通常很有用。這可以透過使用realloc來完成,它返回一個指向指定大小記憶體區域的指標,該區域包含與pointer指向的舊區域相同的資料(截斷為舊大小和新大小的最小值)。如果realloc能夠就地調整記憶體區域的大小,它將分配新的儲存空間,複製所需的資料,並釋放舊指標。如果此分配失敗,realloc將保持原始指標不變,並返回空指標值。在擴充套件的情況下,複製舊資料之外的新記憶體區域是未初始化的(內容不可預測)。函式原型為
void *realloc(void *pointer, size_t size);
如果pointer為 NULL,則 realloc 的行為類似於給定size的 malloc
void *p = malloc(42);
void *p = realloc(NULL, 42); /* equivalent */
在 C89 和 C99 中,長度為 0 的realloc是一個特例。C89 標準明確規定給定的指標將被釋放,返回值要麼為空指標,要麼是指向新分配空間的指標。C99 標準指出該行為是實現定義的。malloc 和 size 為 0 的 realloc 可能返回不同的(空和非空)指標。其他標準,例如 Open Group 的 UNIX 標準,使realloc(p, 0)是否釋放p而無需分配新空間,或者可能釋放p並返回指向至少 0 位元組記憶體的有效指標,成為實現定義的。在所有標準下,NULL 可以在記憶體分配失敗時返回。使用realloc時,應始終使用臨時變數。例如
void *p = malloc(orig_size);
/* and later... */
void *tmp = realloc(p, big_size);
if (tmp != NULL) {
p = tmp; /* OK, assign new, larger storage to p */
} else {
/* handle the problem somehow */
}
如果相反地
void *p = malloc(orig_size);
/* and later... */
p = realloc(p, big_size);
並且如果無法獲得big_size位元組的記憶體,那麼 p 的值為 NULL,我們不再擁有指向先前為 p 分配的記憶體的指標,從而造成記憶體洩漏(見下文)。
malloc和相關函式的錯誤使用經常會導致錯誤。
malloc不能保證成功——如果記憶體不足,或者程式已經超過了它可以引用的記憶體量,malloc將返回一個空指標,這應該始終在分配後檢查。許多程式碼編寫不好的程式沒有檢查malloc是否失敗。這樣的程式將嘗試使用malloc返回的空指標,就好像它指向分配的記憶體一樣。程式很可能會崩潰;在某些環境中,特別是沒有執行虛擬記憶體管理的較舊或較小的平臺上,零是一個有效地址,因此問題將不會被發現。
當malloc、calloc或realloc的呼叫成功時,返回的指向分配記憶體的指標最終應該傳遞給free函式。這將釋放分配的記憶體,使其可以重用以滿足其他記憶體分配請求。如果這樣做沒有完成,分配的記憶體將不會被釋放,直到程序退出(在某些環境中,甚至在退出時也不會被釋放)——換句話說,就會發生記憶體洩漏。通常,記憶體洩漏是由丟失指標造成的,例如沒有使用臨時指標來儲存realloc的返回值,這可能導致原始指標被空指標覆蓋,例如
void *ptr;
size_t size = BUFSIZ;
ptr = malloc(size);
/* some further execution happens here... */
/* now the buffer size needs to be doubled */
if (size > SIZE_MAX / 2) {
/* handle overflow error */
/* . probably appropriate to use free( ptr ) here . */
return (1);
}
size *= 2;
ptr = realloc(ptr, size);
if (ptr == NULL) {
/* the realloc failed (it returned a null pointer), but
the original address in ptr has been lost so the
memory cannot be freed and a leak has occurred */
/* ... */
return 1;
}
/* ... */
在將指標傳遞給free之後,它將成為一個懸掛指標:它引用一個具有未定義內容的記憶體區域,該區域可能不可用。無法訪問指標的值。例如
int *ptr = malloc(sizeof (int));
free(ptr);
*ptr = 7; /* Undefined behavior */
這樣的程式碼具有未定義的行為:其效果可能會有所不同。實際上,即使嘗試讀取已釋放指標的值也會導致未定義行為(這裡)。
通常,系統可能已經將釋放的記憶體重用於其他目的。因此,透過指向已釋放記憶體區域的指標寫入可能會導致覆蓋程式中其他地方的另一段資料。根據覆蓋的資料,這可能會導致資料損壞,或者導致程式在以後的時間崩潰。此問題的特別糟糕的示例是如果將同一個指標兩次傳遞給free,這被稱為雙重釋放。'使用後釋放' 和 '雙重釋放' 錯誤會導致安全漏洞。[6] 為了避免這種情況,一些程式設計師在將指標傳遞給free之後將它們設定為NULL:[7]
free(ptr);
ptr = NULL; /*is safe (throws away the pointer's location).*/
但是,這不會保護對同一個指標的其他別名不被濫用。
另一個問題是,當free傳遞一個未由malloc、realloc或calloc分配的地址時。這可能是由於將指向文字字串的指標或已宣告陣列的名稱傳遞給free造成的,例如
char *msg = "Default message";
int tbl[100];
將上述任一指標傳遞給free會導致未定義的行為。
一個常見的錯誤是釋放記憶體,然後使用它
char *ch_ptr = malloc(20);
for (i = 0; i < 19; i++) ch_ptr[i] = 'A';
i[19] = '\0';
free(ch_ptr);
printf("%s\n", ch_ptr);
這被稱為“釋放後使用”。這將在許多系統上執行。當free()不改變被釋放的記憶體的內容時,就會發生這種情況。C 的標準不保證這種行為。因此,它肯定會有一些系統無法執行。
當函式返回指向分配記憶體的指標時,通常的做法是將返回的指標放入一個變數中,使用記憶體,然後使用指標釋放它
char *ch_ptr = malloc(20);
for (i = 0; i < 19; i++) ch_ptr[i] = 'A';
i[19] = '\0';
printf("%s\n", ch_ptr);
free(ch_ptr);
在某些程式中,記憶體塊會被釋放兩次。這是因為混淆了哪個函式負責記憶體釋放。例如
void main(){
int *p;
p = (int *)malloc(10 * sizeof(int));
f(p);
free(p);
}
void f(int *g){
printf("%d", g);
free(g);
}
這被稱為“雙重釋放”或“多次釋放”。這段程式碼在某些系統上可以執行,但在第二次執行時可能會崩潰釋放.
記憶體管理的實現很大程度上取決於作業系統和架構。一些作業系統為 malloc 提供分配器,而另一些作業系統提供函式來控制某些資料區域。在 C++ 中,通常使用相同的動態記憶體分配器來實現 malloc 和 new 運算子 [需要引用]。因此,以下將其稱為分配器,而不是 malloc。
分配器在 IA-32 架構上的實現通常使用堆或資料段。分配器通常會擴充套件和收縮堆來滿足分配請求。
堆方法存在一些固有的缺陷,完全源於碎片化。與任何記憶體分配方法一樣,堆也會變得碎片化;也就是說,在堆上的已分配空間中,將存在已使用和未使用的記憶體部分。一個好的分配器會在訴諸擴充套件堆之前,嘗試找到一個可用的已分配記憶體區域來使用。這種方法的主要問題是,堆只有兩個重要的屬性:基址,即堆在虛擬記憶體空間中的起點;以及長度,即其大小。堆需要足夠的系統記憶體來填充其整個長度,並且其基址永遠不會改變。因此,任何大塊未使用的記憶體都被浪費了。如果在堆的末尾存在一個小的已使用段,則堆可能會“卡住”在這種位置,這可能會浪費任何數量的地址空間,從幾兆位元組到幾百兆位元組。
Doug Lea 是一個名為 dlmalloc(“Doug Lea 的 Malloc”)的記憶體分配器的作者,其原始碼將自己描述為
“這不是有史以來編寫速度最快、最節省空間、最便攜或
最可調的 malloc。但它是最快的之一,同時也是最節省空間、最便攜和最可調的之一。在這些因素之間取得一致的平衡,使其成為 malloc 密集型程式的良好通用分配器。”
dlmalloc 的第一個實現是在 1987 年建立的。 [8] 它用 C 編寫,並且具有很高的可移植性,已知在所有主要的作業系統和處理器架構以及從中等/小型嵌入式系統到超級計算機的系統上都能很好地工作 [需要引用]。由於其長壽和開源性質,dlmalloc 被廣泛用於教學目的以及作為其他分配器的基礎,其中最著名的是 ptmalloc2/ptmalloc3。從 v2.3 版本開始,GNU C 庫 (glibc) 使用一個修改過的 ptmalloc2,它本身基於 dlmalloc v2.7.0。 [9]
另一個鮮為人知的 dlmalloc 衍生產品是 nedmalloc,它基於 dlmalloc v2.8.4,本質上是 dlmalloc 被每個執行緒的旁路快取包裝,以提高執行併發性。
堆上的記憶體被分配為“塊”,一個 8 位元組對齊的資料結構,包含一個頭和可用記憶體。已分配的記憶體包含 8 或 16 位元組的開銷,用於塊的大小和使用標誌。未分配的塊還在可用空間區域儲存指向其他空閒塊的指標,這使得最小塊大小為 24 位元組。 [9]
未分配的記憶體被分組到大小相似的“bin”中,透過使用塊的雙向連結串列實現(指標儲存在塊內的未分配空間中)。 [9]
對於小於 256 位元組的請求(“smallbin”請求),使用一個簡單的二進位制冪最佳擬合分配器。一個 CPU 特殊操作(在 GCC 上為 __builtin_clz())用於非常快速地找到第一個設定位,併為對應於該最高位位置的 bin 返回一個塊。如果該 bin 中沒有空閒塊,則從下一個最高 bin 中拆分一個塊。
對於大小為 256 位元組或以上但低於 mmap 閾值的請求,即 dlmalloc 所謂的“largebin”請求,dlmalloc 的最新版本使用了一種就地位遍歷演算法。這基於第一個設定位後的每個位狀態來遍歷二叉樹,現代亂序 CPU 可以非常有效地執行此操作,並且對已分配塊的數量幾乎不變。這種演算法的一個很大的優勢是,如果它找不到請求的大小,它會返回具有下一個最大大小的塊,這使得將該塊拆分為所需大小變得非常容易。
對於超過 mmap 閾值的請求,記憶體始終使用 mmap 系統呼叫分配。預設情況下,閾值為 256 KB(ptmalloc2 上為 1 MB),但可以透過呼叫 mallopt 函式更改。 [10] mmap 方法避免了在大型緩衝區到期後,小型分配被困在大型緩衝區末尾的問題,但始終分配整個記憶體頁,在許多架構上,記憶體頁的大小為 4096 位元組。 [11]
如果需要分配小於閾值但小於可用空閒空間的額外記憶體,dlmalloc 可能會使用 brk() 呼叫 Linux 核心來增加堆的大小。增加堆的大小會增加最頂層的塊(荒野塊)的大小,該塊始終未分配,並且由 malloc 特殊處理。 [9]
dlmalloc 具有一個相當弱的空閒空間段合併演算法,主要是因為空閒空間合併往往非常慢,因為會導致 TLB 快取耗盡。它在預設情況下每 (4096) 個 free() 操作呼叫一次,它透過迭代之前從系統請求的每個段來工作,這些段沒有被系統連續返回。它嘗試識別不包含已分配塊的大範圍記憶體,並將它的段分成兩個,並將空閒記憶體返回給系統。如果 dlmalloc 是 VM 系統的唯一使用者,則此演算法效果很好,但是,如果 dlmalloc 與另一個分配器同時使用,則 dlmalloc 的空閒空間合併器可能無法正確識別釋放空閒記憶體的機會。
glibc 對 ptmalloc2 的實現 在這種情況下與 dlmalloc 不同,因為它通常使用 mmap 從核心請求額外記憶體來分配 1Mb 對齊的塊,其原始碼將這些塊稱為arena。ptmalloc2 試圖確保每個執行執行緒都有單獨的 arena,從而允許記憶體分配器內的併發性。
ptmalloc3 透過使 dlmalloc 的 smallbin(如上所述)成為每個執行緒的,對 ptmalloc2 進行了顯著改進。這允許 ptmalloc3 為較小的塊提供無鎖併發,同時仍然允許為 largebin 分配提供單獨的 arena。超過 mmap 閾值的分配仍然完全透過 mmap() 路由。
nedmalloc 與 ptmalloc2 類似,支援多個每個執行緒的 arena,但它還為較小尺寸的塊添加了單獨的每個執行緒的旁路快取,這避免了處理器序列化,類似於 ptmalloc3 的典型 C++ 使用模式。nedmalloc 與下面提到的 Hoard 一樣,能夠修補 Microsoft Windows 二進位制檔案,以在給定程序內用自身替換系統分配器。nedmalloc 的最新版本實現了使用者模式頁分配器,它替換了 mmap(),從而允許記憶體頁儲存在旁路快取中,因此極大地提高了大型分配的速度。
dlmalloc、ptmalloc2、ptmalloc3 和 nedmalloc 都是根據開源許可證釋出的,因此可以供學生學習。
從 FreeBSD 7.0 和 NetBSD 5.0 開始,舊的 malloc 實現 (phkmalloc) 被 Jason Evans 編寫的 jemalloc 替換。這樣做主要是因為 phkmalloc 在多執行緒方面缺乏可擴充套件性。為了避免鎖爭用,jemalloc 為每個 CPU 使用單獨的“arena”。測量多執行緒應用程式中每秒分配次數的實驗表明,這使其能夠隨著執行緒數量線性擴充套件,而對於 phkmalloc 和 dlmalloc,效能與執行緒數量成反比。 [12]
jemalloc 被用作 Firefox 3 beta4pre 及更高版本在 Windows 和 Linux 中的預設分配器,而不是作業系統提供的分配器,除了 Mac OS X。由於碎片化減少,這提高了效能並降低了記憶體消耗。
OpenBSD 中 malloc 函式的實現利用了 mmap。對於大於一頁大小的請求,整個分配都使用 mmap 獲取;較小的尺寸從 malloc 在多個“桶頁”中維護的記憶體池分配,這些桶頁也使用 mmap 分配。在呼叫 free 時,記憶體被釋放並使用 munmap 從程序地址空間取消對映。該系統旨在透過利用 OpenBSD 的 mmap 系統呼叫中實現的地址空間佈局隨機化和間隙頁功能來提高安全性,並檢測使用後釋放錯誤,因為在釋放後,大型記憶體分配將完全取消對映,進一步使用會導致段錯誤並終止程式。
Hoard 記憶體分配器是一個旨在實現可擴充套件記憶體分配效能的分配器。與 OpenBSD 的分配器類似,Hoard 專門使用 mmap,但它以 64 千位元組的塊(稱為超級塊)管理記憶體。Hoard 的堆在邏輯上分為一個全域性堆和多個每個處理器堆。此外,還有一個執行緒本地快取,可以儲存有限數量的超級塊。透過僅從本地每個執行緒或每個處理器堆上的超級塊分配,並將大部分空閒超級塊移到全域性堆中以便其他處理器重用,Hoard 保持低碎片化,同時實現接近線性的可擴充套件性,執行緒數量的增加。[13]
每個執行緒都有用於小型分配的本地儲存。對於大型分配,可以使用 mmap 或 sbrk。 Tcmalloc 具有用於死執行緒本地儲存的垃圾收集。對於多執行緒程式,TCmalloc 被認為比 glibc 的 ptmalloc 快兩倍以上。[14][15]
作業系統核心需要像應用程式一樣分配記憶體。但是,核心中 malloc 的實現通常與 C 庫使用的實現有很大不同。例如,記憶體緩衝區可能需要符合 DMA 強制執行的特殊限制,或者記憶體分配函式可能從中斷上下文呼叫。[16] 這需要與作業系統核心的虛擬記憶體子系統緊密整合的 malloc 實現。
在 Linux 和 Unix 中,kmalloc 和 kfree 在核心中提供了 malloc 和 free 的功能。在 Windows 驅動程式中,ExAllocatePoolWithTag、ExAllocatePoolWithQuotaTag 和 ExFreePoolWithTag 在核心模式下提供 malloc/free 語義功能。
malloc 可以分配的最大記憶體塊大小取決於主機系統,尤其是物理記憶體的大小和作業系統的實現。理論上,最大數量應該是 size_t 型別可以容納的最大值,它是一個與實現相關的無符號整數,表示記憶體區域的大小。最大值為 2CHAR_BIT*sizeof(size_t) − 1,或 C99 標準中的常量 SIZE_MAX。
- ↑ gnu.org 上的 gcc 手冊,2008 年 12 月 14 日訪問
- ↑ "alloca". Man.freebsd.org. 2006-09-05. Retrieved 2011-09-18.
- ↑
malloca()MSDN Visual C++ 開發人員中心頁面。2009 年 3 月 12 日訪問 - ↑ a b 常見問題解答 > 解釋... > 將 malloc 轉換為其他型別,Cprogramming.com,2007 年 3 月 9 日訪問
- ↑ comp.lang.c 常見問題解答列表 · 問題 7.7b,C-FAQ,2007 年 3 月 9 日訪問
- ↑ "CWE - CWE-415:雙重釋放 (2.1)". Cwe.mitre.org. Retrieved 2011-09-18.
- ↑ The Open Group Base Specifications Issue 6,The Open Group,2007 年 3 月 9 日訪問
- ↑ "A Memory Allocator". Gee.cs.oswego.edu. Retrieved 2011-09-18.
- ↑ a b c d Kaempf, Michel (2001). "Vudo malloc tricks". Phrack (57): 8. Retrieved 2009-04-29.
{{cite journal}}: Cite has empty unknown parameters:|coauthors=and|month=(help) - ↑ "Malloc Tunable Parameters". GNU. Retrieved 2009-05-02.
- ↑ Sanderson, Bruce (2004-12-12). "RAM, Virtual Memory, Pagefile and all that stuff". Microsoft Help and Support.
- ↑ http://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf
- ↑ http://www.cs.umass.edu/~emery/pubs/berger-asplos2000.pdf
- ↑ http://goog-perftools.sourceforge.net/doc/tcmalloc.html
- ↑ Mark Callaghan (2009-01-18). "High Availability MySQL: Double sysbench throughput with TCMalloc". Mysqlha.blogspot.com. Retrieved 2011-09-18.
- ↑ "kmalloc()/kfree() include/linux/slab.h". People.netfilter.org. Retrieved 2011-09-18.
- IEEE Std 1003.1 標準中 malloc 的定義
- glibc 分配器基礎設計,作者:Doug Lea
- ptmalloc 主頁,作者:Wolfram Gloger
- Hoard 主頁,作者:Emery Berger
- nedmalloc 主頁,作者:Niall Douglas
- jemalloc 主頁,作者:Jason Evans
- TCMalloc 主頁,由 Google 開發的高效能 malloc
- 簡單的記憶體分配演算法,來自 OSDEV 社群
- Hoard: 適用於多執行緒應用程式的可擴充套件記憶體分配器,作者:Emery Berger
- 可擴充套件的無鎖動態記憶體分配,作者:Maged M. Michael
- 記憶體管理內幕 - 動態分配的選擇、權衡和實現,作者:Jonathan Bartlett
- 記憶體減少 (GNOME) 維基頁面,包含大量關於修復 malloc 的資訊
- C99 標準草案,包括 TC1/TC2/TC3
- 一些關於 C 語言的有用參考資料
- ISO/IEC 9899 - 程式設計語言 - C