Penso che mallinfo() sia quello che vuoi:
#include <malloc.h>
struct mallinfo *info;
info = mallinfo();
printf ("total allocated space: %llu bytes\n", info->uordblks);
printf ("total free space: %llu bytes\n", info->fordblks);
La struttura struct mallinfo è tecnica e specifica dell'implementazione malloc(). Ma le informazioni che vuoi sono lì dentro. Ecco come riporto i valori:
mallinfo.arena = "Total Size (bytes)"
mallinfo.uordblks = "Busy size (bytes)"
mallinfo.fordblks = "Free size (bytes)"
mallinfo.ordblks = "Free blocks (count)"
mallinfo.keepcost = "Top block size (bytes)"
mallinfo.hblks = "Blocks mapped via mmap() (count)"
mallinfo.hblkhd = "Bytes mapped via mmap() (bytes)"
Questi due presumibilmente non sono usati, ma sembrano cambiare sul mio sistema, e quindi potrebbero essere validi:
mallinfo.smblks = "Fast bin blocks (count)"
mallinfo.fsmblks = "Fast bin bytes (bytes)"
E l'altro valore interessante è restituito da "sbrk (0)"
Ci sono un certo numero di possibilità.
Quanto preciso hai bisogno che sia? Puoi ottenere alcuni dati utili tramite cat /proc/${PID}/status | grep VmData .
Puoi #define il tuo malloc() , realloc() , calloc() e free() funzioni, avvolgendo le funzioni reali dietro il proprio contatore. Puoi fare cose davvero interessanti qui con __FILE__, __LINE__ e __func__ per facilitare l'identificazione delle perdite principali in semplici test. Ma strumentizzerà solo il tuo codice!
(Allo stesso modo, puoi anche ridefinire l'operatore nuovo predefinito e eliminazione operatore metodi, sia varianti di array che non di array, ed entrambi lanciano varianti std::bad_alloc e std::nothrow_t. Di nuovo, questo instrumenterà solo il tuo codice!
(Attenzione:sulla maggior parte dei sistemi C++, nuovo alla fine invoca malloc() . Non è necessario. Soprattutto con il nuovo sul posto ! Ma in genere nuovo fa uso di malloc() . (Oppure opera su una regione di memoria che è stata precedentemente malloc()'ed .) Altrimenti ti cimenteresti in cose davvero stravaganti con più gestori di heap...)
Puoi utilizzare sbrk(0) per vedere dove è attualmente impostato il segmento di dati. Non è fantastico. È una misurazione molto grossolana e non tiene conto dei buchi (regioni di memoria inutilizzate) nell'heap. (Stai molto meglio con VmData linea da /proc/${PID}/status .) Ma se stai solo cercando un'idea generale...
Puoi intercettare malloc()/free()/etc scrivendo la tua libreria condivisa e costringendo il tuo processo a usarla al posto delle versioni reali tramite LD_PRELOAD . Puoi usare dlopen()/dlsym() per caricare e invocare il *reale* malloc()/free()/etc . Funziona abbastanza bene. Il codice originale non viene modificato, nemmeno ricompilato. Ma fai attenzione alle situazioni rientranti durante la codifica di questa libreria e che il tuo processo invocherà inizialmente malloc()/calloc()/realloc() prima di dlopen()/dlsym() può completare il caricamento delle funzioni reali.
Potresti dare un'occhiata a strumenti come Valgrind , anche se in realtà è più mirato alle perdite di memoria.
Poi di nuovo, forse mtrace() è quello che vuoi? Oppure __malloc_hook ? Molto proprietario (GNU) e non standard... Ma sei etichettato come "Linux"...
Non c'è niente di facile, automatico modo per farlo, se è quello che stai chiedendo. Fondamentalmente devi tenere manualmente traccia delle allocazioni dell'heap usando una variabile contatore. Il problema è che è difficile controllare quali parti del tuo programma stanno allocando memoria sull'heap, specialmente se stai usando molte librerie fuori dal tuo controllo. Per complicare ulteriormente le cose, ci sono due modi in cui un programma può allocare memoria heap:new
o malloc
. (Per non parlare delle chiamate dirette al sistema operativo come sbrk
.)
Puoi sovrascrivere l'operatore globale new
e fare in modo che ogni chiamata a new aumenti un conteggio globale. Tuttavia, questo non includerà necessariamente le volte in cui il tuo programma chiama malloc
, o quando il tuo programma utilizza un new
specifico della classe oltrepassare. Puoi anche sovrascrivere malloc
utilizzando una macro, ma questo non è necessariamente portatile. E dovresti anche sovrascrivere tutte le variazioni di malloc
, come realloc
, calloc
, ecc. Tutto questo è ulteriormente complicato dal fatto che su alcune implementazioni, new
stesso può chiamare malloc
.
Quindi, essenzialmente, è molto difficile farlo correttamente dall'interno del tuo programma. Consiglierei invece di utilizzare uno strumento di profilazione della memoria.