Doug Lea分配器的奇怪的malloc行为

时间:2011-05-25 11:29:58

标签: c memory-management malloc pic microchip

我有一个非常小的系统,只有16kb的堆,没有mmap,没有交换。我正在使用Doug Lea分配器ftp://g.oswego.edu/pub/misc/malloc-2.8.5.c

的最新2.8.5版本

更新我制作了一个更容易理解的小型测试用例,看看我的问题是什么

如果我分配8kb,释放它,分配12kb,它正在工作(i!= NULL),我可以分配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,它正在工作(i == NULL),i 不能分配12 kb:< / p>

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

在每个时刻,只有一个分配在分配另一个块之前被释放并释放,因此内存永远不会被分段。

2 个答案:

答案 0 :(得分:4)

我得到了Doug Lea的回答:

  

如果试图延长(或   初始化)连续的sbrk段   失败,sysalloc将空格标记为   非连续的,以避免持续的   否则会重新失败   扰乱从MORECORE到。的过渡   MMAP可用时。

     

这导致后续段不会   合并。目前没有   重写此行为的方法。但是你   应该可以解决它   删除第4113-4行

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

将来,我会考虑添加一个   在这个过程中控制这个的方法   其他一些计划支持   页保护

答案 1 :(得分:1)

我认为这段(来自维基百科,所以没有保证)解释了为什么你会看到这种行为:

  

dlmalloc具有相当弱的自由空间段聚结器算法,主要是因为自由空间合并由于导致TLB高速缓存耗尽而趋于极慢。它被称为每个(默认情况下)4096个free()操作,并且它通过迭代先前从系统请求的每个未被系统连续返回的段来工作。它尝试识别大范围的内存,这些内存不包含已分配的块,并将其段拆分为两个,并将可用内存返回给系统。如果dlmalloc是VM系统的唯一用户,则该算法很有效,但是如果dlmalloc与另一个分配器同时使用,则dlmalloc的可用空间聚结器可能无法正确识别释放空闲内存的机会。

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