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: ???
| | |
......
Cライブラリ関数free()
は、メモリをカーネルに返すことができますが、そうする必要はありません。
malloc()
の一部の実装は、sbrk()
システムコールを介して「ヒープ」とそれ以外の場合は未使用のアドレス空間(「システムブレーク」)の間の境界を移動し、それらの大きな割り当ての小さな部分を除外します。小さい部分をすべて割り当て解除しないと、free()
はメモリをOSに実際に返すことができません。
同じ理由がmalloc()
を使用しないsbrk(2)
実装にも当てはまりますが、mmap("/dev/zero")
または何かを使用している可能性があります。参照が見つかりませんが、 BSDのいずれかがメモリのページを取得するためにmmap()
を使用したことを覚えているようです。それにもかかわらず、すべてのサブ割り当てがプログラムによって割り当て解除されない限り、free()
はオペレーティングシステムにページを返すことができません。
一部のmalloc()
実装は、システムにメモリを返します。 ChorusOS(?) は明らかにそうでした。システムブレークまたはmunmap()'ed
ページを移動したかどうかは明確ではありません。
ここにメモリアロケータに関する論文があります 「仮想メモリマネージャに積極的に空きページをあきらめる」ことでパフォーマンスを向上させます。 トークスライドショー アロケータについて。