free()はプロセスのメモリのマッピングを解除しますか?


8

Linux 2.6.16カーネルでCプログラムを実行しています。プログラムにメモリリークはないと思いますが、プログラムのメモリ消費量は、特定の操作後も安定しており、減少しません。'ps v'コマンドを使用して、プログラムのRSS値を監視しています。

valgrind Massifツールは、私のプロセスでヒープの大部分がmmapによって割り当てられていることを示しています。しかし、コードによると、これらの割り当ては、操作の完了後に解放されているはずです。それは解放されたメモリがまだマップされているか、プロセスのRSS値に貢献しているためでしょうか?

どんな洞察も非常に高く評価されます!

以下は、valgrind Massifレポートの抜粋です。プログラムで使用されるすべてのメモリを測定するために、massifツールの--pages-as-heapオプションをオンにしたことに注意してください。

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 85 701,483,989,262      173,576,192      173,576,192             0            0
 86 704,352,949,469      173,367,296      173,367,296             0            0
 87 707,582,275,643      173,367,296      173,367,296             0            0
 88 710,536,145,814      173,367,296      173,367,296             0            0
100.00% (173,367,296B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc.
->53.40% (92,581,888B) 0x649248B: mmap (in /lib64/tls/libc.so.6)
| ->41.13% (71,303,168B) 0x6446D85: _int_malloc (in /lib64/tls/libc.so.6)
| | ->39.31% (68,157,440B) 0x6448D62: calloc (in /lib64/tls/libc.so.6)
......[my own functions are omitted]
->35.28% (61,157,376B) 0x400F51B: mmap (in /lib64/ld-2.3.3.so)
| ->28.81% (49,954,816B) 0x4004CE8: _dl_map_object_from_fd (in /lib64/ld-2.3.3.so)
| | ->28.81% (49,954,816B) 0x400636B: _dl_map_object (in /lib64/ld-2.3.3.so)
| |   ->18.89% (32,755,712B) 0x400AB42: openaux (in /lib64/ld-2.3.3.so)
| |   | ->18.89% (32,755,712B) 0x400AF7C: _dl_catch_error (in /lib64/ld-2.3.3.so)
| |   |   ->18.89% (32,755,712B) 0x4009FCF: _dl_map_object_deps (in /lib64/ld-2.3.3.so)
| |   |     ->18.89% (32,755,712B) 0x40021FD: dl_main (in /lib64/ld-2.3.3.so)
| |   |       ->18.89% (32,755,712B) 0x400E7F6: _dl_sysdep_start (in /lib64/ld-2.3.3.so)
| |   |         ->18.89% (32,755,712B) 0x4001477: _dl_start (in /lib64/ld-2.3.3.so)
| |   |           ->18.89% (32,755,712B) 0x4000CF6: ??? (in /lib64/ld-2.3.3.so)
| |   |             ->18.89% (32,755,712B) 0x0: ???
| |   |               ->18.89% (32,755,712B) 0x7FF0003D5: ???
| |   |                 ->18.89% (32,755,712B) 0x7FF0003E4: ???
| |   |
......

なぜ使ってないのmunmapmunmap(2)
Mikel

共有ライブラリを使用していますか?あなたは、出力の関連する部分を提供できるvalgrindだけでなく、/proc/<PID>/maps
ミケル、

glibc mallocおよびfreeには実装があるため、munmapは使用しません。はい、共有ライブラリが使用されます。なぜそれが重要なのですか?valgrindレポートの関連部分がメインの質問に追加されます。
ミシェル・


@michelle私はあなたが電話をしているのだと思っていましたmmap。しかし今、私は理解していると思います:malloc/をcalloc呼び出していmmapますが、それは
Mikel、

回答:


5

Cライブラリ関数free()は、メモリをカーネルに返すことができますが、そうする必要はありません。

一部の実装ではmalloc()sbrk()システムコールを介して「ヒープ」とそれ以外の場合は未使用のアドレス空間(「システムブレーク」)の間の境界を移動し、それらの大きな割り当ての小さな部分を処理します。小さな部分をすべて割り当てfree()解除しないと、メモリをOSに戻すことができません。

同じ理由がをmalloc()使用しない実装にも当てはまりますsbrk(2)が、おそらく使用するmmap("/dev/zero")か何かです。参照を見つけることができませんが、BSDのいずれかmmap()がメモリのページを取得するためにそのように使用したことを覚えているようです。それでも、free()すべてのサブ割り当てがプログラムによって割り当て解除されない限り、オペレーティングシステムにページを返すことはできません。

一部のmalloc()実装は、システムにメモリを返します。ChorusOS(?)は明らかにそうしました。システムブレークまたはmunmap()'edページを移動したかどうかは明確ではありません。

これは、「仮想メモリマネージャに空きページを積極的に放棄する」ことでパフォーマンスを向上させるメモリアロケータに関する論文です。 アロケータについて説明するスライドショー


free()はメモリをOSに返さないことを理解しています。しかし、free()はメモリのマップを解除しますか、それともglibcメモリアロケータによってマップされるメモリは残っていますか?
ミシェル・

「free()は、すべてのサブ割り当てがプログラムによって割り当て解除されない限り、オペレーティングシステムにページを返すことができません。」よくわかりません。「サブ割り当て」について説明していただけますか?
ミシェル

1
@michelle:4192バイトのページサイズを想定します。プログラムがmalloc(4186)を呼び出してから、malloc(8)を呼び出します。プログラムがすべてのページを割り当てました。プログラムは、4186バイトの割り当てでfree()を呼び出します。8バイトの割り当てがfree()されていないため、free()はページをマップ解除できません。
Bruce Ediger 2012年

それは理にかなっている。ブルースに感謝します。したがって、私の推測では、ページがまだマッピングされている場合、その中のすべてのデータは、valgrind測定によって考慮に入れられますが、一部はすでに解放されています。正しい?
ミシェル・
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.