Apakah free () menghapus peta memori suatu proses?

8

Saya menjalankan program C di kernel Linux 2.6.16. Saya tidak berpikir ada kebocoran memori dalam program saya namun konsumsi memori untuk program tetap stabil setelah operasi tertentu dan tidak berkurang. Saya menggunakan perintah 'ps v' untuk memantau nilai RSS program saya.

Alat massif valgrind menunjukkan sebagian besar tumpukan dialokasikan oleh mmap dalam proses saya. Tetapi menurut kode alokasi tersebut seharusnya dibebaskan setelah operasi selesai. Apakah karena memori yang dibebaskan masih dipetakan dan / atau masih berkontribusi pada nilai RSS proses?

Wawasan apa pun akan sangat dihargai!

Di bawah ini adalah cuplikan dari laporan massif valgrind. Catatan Saya telah mengaktifkan opsi --pages-as-heap untuk alat massif untuk mengukur semua memori yang digunakan oleh program.

--------------------------------------------------------------------------------
  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: ???
| |   |
......
michelle
sumber
Kenapa kamu tidak menggunakan munmap? munmap (2)
Mikel
Apakah Anda menggunakan perpustakaan bersama? Bisakah Anda memberikan bagian output yang relevan valgrindjuga /proc/<PID>/maps?
Mikel
Kami tidak menggunakan munmap sejak glibc malloc dan gratis memiliki implementasinya. Ya, perpustakaan bersama digunakan. Mengapa itu penting? Bagian relevan dari laporan valgrind ditambahkan ke pertanyaan utama.
michelle
Lihat alokasi memori UNIX vs Windows
Gilles 'SO- stop being evil'
@ Michelle, saya pikir maksud Anda Anda menelepon mmap. Tapi sekarang saya pikir saya mengerti: Anda menelepon malloc/ calloc, dan itu memanggil mmap?
Mikel

Jawaban:

5

Fungsi C-library free()dapat, tetapi tidak harus, mengembalikan memori ke kernel.

Beberapa implementasi malloc()memindahkan batas antara "heap" dan ruang alamat yang tidak digunakan ("system break") melalui sbrk()system call, kemudian membagikan bagian kecil dari alokasi besar tersebut. Tanpa setiap bagian kecil dialokasikan, free()tidak dapat benar-benar mengembalikan memori ke OS.

Alasan yang sama berlaku untuk malloc()implementasi yang tidak menggunakan sbrk(2), tetapi mungkin menggunakan mmap("/dev/zero")atau sesuatu .. Saya tidak dapat menemukan referensi, tetapi saya sepertinya ingat bahwa salah satu dari BSD menggunakan mmap()cara itu untuk mendapatkan halaman memori. Namun demikian, free()tidak dapat mengembalikan halaman ke sistem operasi kecuali setiap sub-alokasi tidak dialokasikan oleh program.

Beberapa malloc()implementasi mengembalikan memori ke sistem: ChorusOS (?) Ternyata melakukannya. Tidak jelas apakah itu memindahkan sistem, atau munmap()'edhalaman.

Berikut ini makalah tentang pengalokasi memori yang meningkatkan kinerja dengan "secara agresif menyerahkan halaman gratis ke manajer memori virtual". Pertunjukan slide untuk pembicaraan tentang pengalokasi.

Bruce Ediger
sumber
Saya mengerti gratis () tidak mengembalikan memori ke OS. Tetapi apakah free () tidak memetakan memori atau apakah memori tetap dipetakan oleh pengalokasi memori glibc?
michelle
"gratis () tidak dapat mengembalikan halaman ke sistem operasi kecuali setiap sub-alokasi tidak dialokasikan oleh program." Saya tidak begitu mengerti hal ini. Bisakah Anda menjelaskan 'sub-alokasi'?
michelle
1
@ Michael: misalkan ukuran halaman 4192 byte. Suatu program memanggil malloc (4186) dan kemudian malloc (8). Program telah mengalokasikan semua halaman. Program ini memanggil bebas () pada alokasi 4186-byte. free () tidak dapat menghapus peta halaman karena alokasi 8-byte belum bebas () diedit.
Bruce Ediger
Itu masuk akal. Terima kasih Bruce. Jadi tebakan saya adalah ketika halaman masih dipetakan, semua data di dalamnya masih dipertimbangkan oleh pengukuran valgrind meskipun beberapa sudah dibebaskan. Benar?
michelle