Hebt free () die Zuordnung des Speichers eines Prozesses auf?

8

Ich führe ein C-Programm unter Linux 2.6.16 aus. Ich glaube nicht, dass es Speicherlecks in meinem Programm gibt, aber der Speicherverbrauch für das Programm bleibt nach bestimmten Vorgängen stabil und nimmt nicht ab. Ich verwende den Befehl 'ps v', um den RSS-Wert meines Programms zu überwachen.

Das Valgrind-Massiv-Tool zeigt an, dass ein großer Teil des Heaps in meinem Prozess von mmap zugewiesen wird. Gemäß dem Code sollten diese Zuordnungen jedoch nach Abschluss der Vorgänge freigegeben worden sein. Liegt es daran, dass der freigegebene Speicher noch zugeordnet ist und / oder immer noch zum RSS-Wert des Prozesses beiträgt?

Jeder Einblick wird sehr geschätzt!

Unten ist der Ausschnitt aus dem Valgrind-Massivbericht. Hinweis Ich habe die Option --pages-as-heap für das Massiv-Tool aktiviert, um alle vom Programm verwendeten Speicher zu messen.

--------------------------------------------------------------------------------
  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
quelle
Warum benutzt du nicht munmap? Munmap (2)
Mikel
Verwenden Sie gemeinsam genutzte Bibliotheken? Können Sie relevante Teile der Ausgabe von valgrindsowie bereitstellen /proc/<PID>/maps?
Mikel
Wir verwenden keine Munmap, da glibc malloc und free die Implementierungen hat. Ja, es werden gemeinsam genutzte Bibliotheken verwendet. Wieso spielt das eine Rolle? Die relevanten Teile des Valgrind-Berichts werden der Hauptfrage hinzugefügt.
Michelle
Siehe UNIX vs Windows Speicherfreigabe
Gilles 'SO - hör auf böse zu sein'
@michelle Ich dachte du meintest du rufst an mmap. Aber jetzt denke ich zu verstehen: Du rufst malloc/ callocan und es ruft mmap?
Mikel

Antworten:

5

Die C-Library-Funktion free()kann, muss aber nicht, Speicher an den Kernel zurückgeben.

Einige Implementierungen malloc()verschieben die Grenze zwischen "Heap" und ansonsten nicht verwendetem Adressraum (der "Systembruch") über den sbrk()Systemaufruf und verteilen dann kleinere Teile dieser großen Zuordnungen. Ohne die Zuweisung jedes kleineren Teils free()kann der Speicher nicht wirklich an das Betriebssystem zurückgegeben werden.

Der gleiche Grund gilt für malloc()Implementierungen, die nicht verwendet werden sbrk(2), aber möglicherweise verwenden mmap("/dev/zero")oder so. Ich kann keine Referenz finden, aber ich scheine mich daran zu erinnern, dass die eine oder andere BSD auf mmap()diese Weise verwendet wurde, um Speicherseiten abzurufen. Es free()kann jedoch keine Seite an das Betriebssystem zurückgegeben werden, es sei denn, jede Unterzuweisung wird vom Programm freigegeben.

Einige malloc()Implementierungen geben Speicher an das System zurück: ChorusOS (?) Hat dies anscheinend getan. Es ist nicht klar, ob der Systembruch oder die munmap()'edSeiten verschoben wurden .

Hier ist ein Artikel über einen Speicherzuweiser , der die Leistung verbessert, indem er "freie Seiten aggressiv an den virtuellen Speichermanager abgibt". Diashow für einen Vortrag über den Allokator.

Bruce Ediger
quelle
Ich verstehe, dass free () keine Erinnerungen an das Betriebssystem zurückgibt. Aber hebt free () die Zuordnung des Speichers auf oder muss der Speicher noch vom glibc-Speicherzuweiser zugeordnet werden?
Michelle
"free () kann keine Seite an das Betriebssystem zurückgeben, es sei denn, jede Unterzuweisung wird vom Programm freigegeben." Ich verstehe das nicht wirklich. Könnten Sie die Unterzuordnung erklären?
Michelle
1
@michelle: Angenommen, eine Seitengröße von 4192 Bytes. Ein Programm ruft malloc (4186) und dann malloc (8) auf. Das Programm hat eine ganze Seite zugewiesen. Das Programm ruft bei der 4186-Byte-Zuweisung free () auf. free () kann die Zuordnung der Seite nicht aufheben, da die 8-Byte-Zuordnung nicht free () ist.
Bruce Ediger
Das macht Sinn. Danke Bruce. Wenn die Seite noch zugeordnet ist, werden alle darin enthaltenen Daten bei der Valgrind-Messung berücksichtigt, obwohl einige bereits freigegeben sind. Richtig?
Michelle