Free () annulla la mappatura della memoria di un processo?


8

Sto eseguendo un programma C su kernel Linux 2.6.16. Non credo che ci siano perdite di memoria nel mio programma, tuttavia il consumo di memoria per il programma rimane stabile dopo alcune operazioni e non diminuisce. Uso il comando 'ps v' per monitorare il valore RSS del mio programma.

Lo strumento massiccio valgrind mostra che una grande porzione di heap è allocata da mmap nel mio processo. Tuttavia, secondo il codice, tali allocazioni avrebbero dovuto essere liberate al termine delle operazioni. È perché la memoria liberata è ancora mappata e / o contribuisce ancora al valore RSS del processo?

Qualsiasi approfondimento sarà molto apprezzato!

Di seguito è riportato il ritaglio del rapporto sul massiccio di Valgrind. Nota Ho attivato l'opzione --pages-as-heap per lo strumento del massiccio per misurare tutte le memorie utilizzate dal programma.

--------------------------------------------------------------------------------
  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: ???
| |   |
......

Perché non stai usando munmap? munmap (2)
Mikel

Stai usando librerie condivise? Potete fornire parti rilevanti di uscita da valgrindcosì come /proc/<PID>/maps?
Mikel,

Non usiamo munmap poiché glibc malloc e free ha le implementazioni. Sì, vengono utilizzate le librerie condivise. Perché è importante? Le parti pertinenti del rapporto valgrind vengono aggiunte alla domanda principale.
michelle,


@michelle Pensavo volessi dire che stavi chiamando mmap. Ma ora penso di capire: stai chiamando malloc/ calloc, e sta chiamando mmap?
Mikel

Risposte:


5

La funzione C-library free()può, ma non è necessario, restituire memoria al kernel.

Alcune implementazioni malloc()spostano il confine tra "heap" e lo spazio degli indirizzi altrimenti inutilizzato ("interruzione del sistema") tramite la sbrk()chiamata di sistema, quindi eliminano pezzi più piccoli di tali allocazioni di grandi dimensioni. Senza disassegnare ogni pezzo più piccolo, free()non è possibile restituire la memoria al sistema operativo.

Lo stesso motivo si applica alle malloc()implementazioni che non usano sbrk(2), ma forse usano mmap("/dev/zero")o qualcosa del genere. Non riesco a trovare un riferimento, ma mi sembra di ricordare che l'uno o l'altro dei BSD ha usato mmap()quel modo per ottenere pagine di memoria. Tuttavia, free()non è possibile restituire una pagina al sistema operativo a meno che ogni sub-allocazione non sia allocata dal programma.

Alcune malloc()implementazioni restituiscono memoria al sistema: apparentemente ChorusOS (?) . Non è chiaro se ha spostato l'interruzione di sistema o le munmap()'edpagine.

Ecco un articolo su un allocatore di memoria che migliora le prestazioni "rinunciando in modo aggressivo alle pagine gratuite per il gestore della memoria virtuale". Presentazione per un discorso sull'allocatore.


Capisco che free () non restituisce ricordi al sistema operativo. Ma free () non mappare la memoria o la memoria rimane per essere mappata dall'allocatore di memoria glibc?
michelle,

"free () non può restituire una pagina al sistema operativo a meno che ogni sub-allocazione non sia deallocata dal programma." Non lo capisco davvero. Potresti spiegare la "sub-allocazione"?
michelle,

1
@michelle: supponiamo una dimensione di pagina di 4192 byte. Un programma chiama malloc (4186) e quindi malloc (8). Il programma ha assegnato una pagina intera. Il programma chiama free () sull'allocazione a 4186 byte. free () non può annullare la mappatura della pagina perché l'allocazione a 8 byte non è stata free () 'ed.
Bruce Ediger,

Questo ha senso. Grazie Bruce. Quindi la mia ipotesi è quando la pagina è ancora mappata, tutti i dati in essa contenuti sono ancora presi in considerazione dalla misurazione di Valgrind anche se alcuni sono già stati liberati. Corretta?
Michele
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.