2011-05-25 49 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