2011-06-17 56 views
4

我正在用C中的malloc進行實驗,我發現malloc在分配內存後會浪費一些空間。下面是我用來測試的mallocC中的malloc內存分配方案

#include <stdlib.h> 
#include <string.h> 

int main(){ 
    char* a; 
    char* b; 
    a=malloc(2*sizeof(char)); 
    b=malloc(2*sizeof(char)); 
    memset(a,9,2); 
    memset(b,9,2); 
    return 0; 
} 

在下面的圖片的右側中間的(爲了清楚而以新標籤中打開圖像),你可以看到內存內容的代碼段; 0x804b008是地址指向通過變量'a'和0x804b018是變量'b'指向的內存。從0x804b00a 0x804b017到內存之間發生了什麼?事情是即使我試圖分配3*sizeof(char)而不是2*sizeof(char)字節的內存內存佈局是一樣的!那麼,有什麼我失蹤?

gdb interface

+0

除了下面的答案,值得指出sizeof(char)= 1的定義,所以沒有一點乘以它。 –

+0

@richardkettlewell這是正確的..但我已習慣於任何方式使用它的可讀性 – nagavamsikrishna

回答

8

malloc()被允許,因爲它要浪費盡可能多的空間 - 該標準沒有指定任何實施。你具有的唯一保證是大約對準(§7.20.3內存管理功能):

的指針返回,如果分配成功被適當地對準,使得它可以被分配給一個指針到任何類型的對象然後用於在分配的空間中訪問這樣的對象或這樣的對象的數組(直到空間被明確地解除分配)。

你的實現似乎返回你最小8字節對齊的指針。

+0

什麼是您指的是7.20.3?這是C標準書的一個章節嗎?如果是這樣,你能否指給我那本書。 – nagavamsikrishna

+1

@ vamsi,是的,它來自C規範。 PDF鏈接:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf –

3

Memory Alignment!這對x86的性能很有好處,在ARM等一些體系結構中也是強制性的。

大多數CPU需要的對象和變量駐留在系統內存中特定偏移。例如,32位處理器需要一個4字節的整數位於一個可以被4整除的存儲器地址處。這個要求被稱爲「存儲器對齊」。因此,一個4字節的int可以位於內存地址0x2000或0x2004處,但不在0x2001處。在大多數Unix系統上,嘗試使用未對齊的數據會導致總線錯誤,從而完全終止程序。在英特爾處理器上,支持使用未對齊的數據,但性能損失很大。因此,大多數編譯器根據它們的類型和正在使用的特定處理器自動對齊數據變量。這就是爲什麼結構和類佔據大小往往比其成員的

http://www.devx.com/tips/Tip/13265

0

大多數現代malloc()實施的總和分配中的兩個大國,有一個最小的分配大小,以減少碎片因爲古怪的大小通常只能在足夠的連續分配free()d才能製作更大的塊時重新使用。 (它也加速了整體連續分配,IIRC。)還要記住塊開銷;要獲得塊大小,您需要添加一些金額(8 GNU malloc(),IIRC)內部管理使用。

0

malloc只能保證返回一塊內存,至少與您給它的大小一樣大。但是,處理器在以內存8個字節的倍數開始的內存塊操作時通常效率更高。查詢字大小瞭解更多信息。

2

堆由實現處理,不一定像您期望的那樣。該標準明確不保證任何有關順序或連續性。有兩個主要的原因會導致使用更多的堆空間,而不是您所要求的。

首先,分配的內存必須對齊,以便適用於任何類型的對象。通常情況下,計算機希望N字節的原始數據對象以N的倍數分配,因此您不能得到malloc()以返回不是8的倍數的值。

其次,堆需要管理,以便free()允許重用內存。這意味着堆管理器需要跟蹤已分配和未分配的塊及其大小。一種做法是在每個塊之前將一些信息粘貼在內存中,這樣管理員就可以知道要釋放哪些大小的塊以及哪些塊可以被重用。如果這就是你的系統所做的,那麼在分配的塊之間將會使用更多的內存,並且在8字節的對齊限制下,可能無法獲得小於16字節的分配。