1

ヒープが 16kb しかなく、mmap も swap もない非常に小さなシステムを使用しています。Doug Lea アロケータftp://g.oswego.edu/pub/misc/malloc-2.8.5.cの最新バージョン 2.8.5 を使用しています。

更新 理解しやすく、何が問題なのかを確認するための小さなテストケースを作成しました

8kb を割り当て、解放し、12kb を割り当てると、それは機能し (i != NULL)、12kb を割り当てることができます。

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)、12kb を割り当てることができません:

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

常に 1 つの割り当てのみが行われ、別のブロックを割り当てる前に解放されるため、メモリが断片化されることはありません。

4

2 に答える 2

4

Doug Lea からの回答がありました。

連続した sbrk のセグメントを拡張 (または初期化) しようとして失敗した場合、sysalloc はスペースを非連続としてマークし、使用可能な場合に MORECORE から MMAP への移行を中断する継続的な再失敗を回避します。

これにより、後続のセグメントがマージできなくなります。現在、この動作をオーバーライドする方法はありません。ただし、行 4113-4 を削除することで回避できるはずです。

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

将来的には、ページ保護の他の計画されたサポートの過程で、これを制御する方法を追加することを検討します

于 2011-05-26T14:21:18.683 に答える
1

この段落(ウィキペディアからのものであるため、保証はありません)は、この動作が見られる理由を説明していると思います。

dlmallocには、かなり弱い自由空間セグメント合体アルゴリズムがあります。これは主に、TLBキャッシュの枯渇を引き起こすため、自由空間合体が非常に遅くなる傾向があるためです。これは、(デフォルトでは)4096のfree()操作ごとに呼び出され、システムから連続して返されなかった、システムから以前に要求された各セグメントを反復処理することによって機能します。割り当てられたブロックを含まない広範囲のメモリを識別し、そのセグメントを2つに分割して、空きメモリをシステムに戻します。このアルゴリズムは、dlmallocがVMシステムの唯一のユーザーである場合にうまく機能しますが、dlmallocが別のアロケータと同時に使用される場合、dlmallocの空き領域コアレッサーは空きメモリ解放の機会を正しく識別できない可能性があります。

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

于 2011-05-25T11:41:27.067 に答える