2011-05-25 45 views
1

我有一個非常小的系統,只有16kb的堆,沒有mmap,沒有交換。我使用Doug Lea的分配程序的最新版本2.8.5 ftp://g.oswego.edu/pub/misc/malloc-2.8.5.cDoug Lea分配器的奇怪malloc行爲

UPDATE我做了一個小測試情況下更容易理解,看看有什麼是我的問題

如果我分配8KB,釋放它(!I = NULL),分配12KB,它的工作,我可以分配12 kb的:

char *i; 
dlstats(); 
i = dlmalloc(8192); 
printf("DEBUG: %p\n", i); 
dlstats(); 
dlfree(i); 
dlstats(); 
i = dlmalloc(12288); 
printf("DEBUG: %p\n", i); 
dlstats(); 
dlfree(i); 
dlstats(); 

顯示:

heap 0xa00003f0 sbrk 0xa00003f0 arena 0 ordblks 0 usmblks 0 uordblks 0 fordblks 0 keepcost 0 
DEBUG: 0xa00003f8 
heap 0xa00003f0 sbrk 0xa0002440 arena 8272 ordblks 1 usmblks 8272 uordblks 8200 fordblks 72 keepcost 32 
heap 0xa00003f0 sbrk 0xa0002440 arena 8272 ordblks 1 usmblks 8272 uordblks 0 fordblks 8272 keepcost 8232 
DEBUG: 0xa00003f8 
heap 0xa00003f0 sbrk 0xa0003460 arena 12400 ordblks 1 usmblks 12400 uordblks 12296 fordblks 104 keepcost 64 
heap 0xa00003f0 sbrk 0xa0003460 arena 12400 ordblks 1 usmblks 12400 uordblks 0 fordblks 12400 keepcost 12360 

如果我第一次分配太大緩衝(30KB),然後我分配8KB,無它,配備12KB,它的工作(我== NULL),我無法分配12 KB:

char *i; 
dlstats(); 
i = dlmalloc(30000); 
printf("DEBUG: %p\n", i); 
dlstats(); 
i = dlmalloc(8192); 
printf("DEBUG: %p\n", i); 
dlstats(); 
dlfree(i); 
dlstats(); 
i = dlmalloc(12288); 
printf("DEBUG: %p\n", i); 
dlstats(); 
dlfree(i); 
dlstats(); 

顯示器:

heap 0xa00003f0 sbrk 0xa00003f0 arena 0 ordblks 0 usmblks 0 uordblks 0 fordblks 0 keepcost 0 
DEBUG: 0x0 
heap 0xa00003f0 sbrk 0xa00003f0 arena 0 ordblks 0 usmblks 0 uordblks 0 fordblks 0 keepcost 0 
DEBUG: 0xa00003f8 
heap 0xa00003f0 sbrk 0xa0002430 arena 8256 ordblks 1 usmblks 8256 uordblks 8200 fordblks 56 keepcost 16 
heap 0xa00003f0 sbrk 0xa0002430 arena 8256 ordblks 1 usmblks 8256 uordblks 0 fordblks 8256 keepcost 8216 
DEBUG: 0x0 
heap 0xa00003f0 sbrk 0xa0002430 arena 8256 ordblks 1 usmblks 8256 uordblks 0 fordblks 8256 keepcost 8216 
heap 0xa00003f0 sbrk 0xa0002430 arena 8256 ordblks 1 usmblks 8256 uordblks 0 fordblks 8256 keepcost 8216 

在每一個時刻,只有一個已做出分配和分配之前釋放另一個塊所以內存不應該被割裂。

+0

您正在循環中調用dlstats() - 您確定此調用本身不需要堆上的某些內存?您是否嘗試過沒有調用dlstats? – 2011-05-25 11:37:42

+0

@Frank:dlstats沒有分配內存,我嘗試不調用它們,我有相同的行爲 – acemtp 2011-05-25 15:00:36

+0

我將測試用例更改爲一個簡單的測試用例。似乎調用malloc如果太大的尺寸會產生問題,我不明白爲什麼 – acemtp 2011-05-25 15:01:17

回答

4

我不得不從Doug Lea的答案:

如果試圖延長(或 初始化)連續SBRK的段 失敗,sysalloc標誌着空間 非連續,以避免連續的 再次失敗,否則 中斷從MORECORE轉換到 MMAP時可用。

這會導致後續段不爲 爲可合併。目前沒有 方式來覆蓋此行爲。但是你 應該能夠解決它通過消除 線4113-4

else 
    disable_contiguous(m); /* Don't try contiguous path in the future */ 

在將來,我會考慮增加一個 方式的 一些其他課程,以控制該計劃支持 頁面保護

1

我覺得這一段(從維基百科,所以沒有保證)解釋了爲什麼你看到此行爲:

dlmalloc有一個相當薄弱的自由空間段聚結器算法,主要是因爲自由空間凝聚往往非常由於導致TLB緩存耗盡而變慢。它被稱爲每個(默認情況下)4096個free()操作,它通過迭代系統中以前請求的每個段,並且這些段不是由系統連續返回的。它試圖識別大範圍的內存,其中不包含分配的塊並將其分段分成兩部分,並將可用內存返回給系統。如果dlmalloc是虛擬機系統的唯一用戶,則此算法運行良好,但如果dlmalloc與另一個分配器同時使用,則dlmalloc的可用空間聚合器可能無法正確識別釋放內存的機會。

http://en.wikipedia.org/wiki/Malloc#dlmalloc_and_its_derivatives

+0

您確定此信息是最新的嗎?我認爲被誤導的「優化」已被刪除... – 2011-05-25 12:20:52

+0

@R否,根本不確定。這是在維基百科,並且描述只是匹配他的模擬。 – RedX 2011-05-25 12:33:28

+0

我改變了測試用例,現在它不能與合併算法有關。檢查新的測試,唯一的區別是它不起作用,如果我第一次分配一個太大的緩衝區。 – acemtp 2011-05-25 15:02:06