Ich denke, mallinfo() ist das, was Sie wollen:
#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);
Die struct mallinfo-Struktur ist technisch und spezifisch für die malloc()-Implementierung. Aber die gewünschten Informationen sind darin enthalten. So berichte ich die Werte:
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)"
Diese beiden werden angeblich nicht verwendet, aber sie scheinen sich auf meinem System zu ändern und könnten daher gültig sein:
mallinfo.smblks = "Fast bin blocks (count)"
mallinfo.fsmblks = "Fast bin bytes (bytes)"
Und der andere interessante Wert wird von "sbrk (0)"
zurückgegebenEs gibt eine Reihe von Möglichkeiten.
Wie genau muss es sein? Einige nützliche Daten erhalten Sie über cat /proc/${PID}/status | grep VmData .
Sie können #define Ihr eigenes malloc() , realloc() , calloc() und kostenlos() Funktionen und verpacken die eigentlichen Funktionen hinter Ihrem eigenen Zähler. Sie können hier mit __FILE__, __LINE__ und __func__ wirklich coole Dinge tun, um das Identifizieren von Kernlecks in einfachen Tests zu erleichtern. Aber es wird nur Ihr eigener Code instrumentiert!
(Ähnlich können Sie auch den Standard operator new neu definieren und Operator löschen Methoden, sowohl Array- als auch Nicht-Array-Varianten, und beide werfende std::bad_alloc- und std::nothrow_t-Varianten. Auch hier wird nur Ihr eigener Code instrumentiert!)
(Achtung:Auf den meisten C++-Systemen ist new ruft schließlich malloc() auf . Es muss nicht. Vor allem mit Inplace neu ! Aber typischerweise neu verwendet malloc() . (Oder es arbeitet mit einem Speicherbereich, der zuvor mit malloc() bearbeitet wurde .) Sonst würdest du mit mehreren Heap-Managern in wirklich abgefahrene Sachen geraten...)
Sie können sbrk(0) verwenden um zu sehen, wo das Datensegment aktuell eingestellt ist. Das ist nicht so toll. Dies ist eine sehr grobe Messung und berücksichtigt keine Löcher (nicht verwendete Speicherbereiche) im Heap. (Mit VmData sind Sie viel besser dran Zeile von /proc/${PID}/status .) Aber wenn Sie nur nach einer allgemeinen Idee suchen...
Sie können malloc()/free()/etc abfangen indem Sie Ihre eigene gemeinsam genutzte Bibliothek schreiben und Ihren Prozess dazu zwingen, sie anstelle der echten Versionen über LD_PRELOAD zu verwenden . Sie können dlopen()/dlsym() verwenden um das *echte* malloc()/free()/etc zu laden und aufzurufen . Das funktioniert ganz wunderbar. Der Originalcode ist unverändert, nicht einmal neu kompiliert. Aber seien Sie sich bewusst, dass beim Codieren dieser Bibliothek wiedereintretende Situationen auftreten und dass Ihr Prozess anfänglich malloc()/calloc()/realloc() aufruft vor dlopen()/dlsym() kann das Laden der eigentlichen Funktionen abschließen.
Sie können sich Tools wie Valgrind ansehen , obwohl das eher auf Speicherlecks abzielt.
Dann wieder vielleicht mtrace() willst du? Oder __malloc_hook ? Sehr proprietär (GNU) &nicht standardisiert... Aber Sie sind mit "Linux" getaggt...
Es gibt kein einfaches, automatisches Weg, es zu tun, wenn Sie danach fragen. Sie müssen die Heap-Zuweisungen im Grunde selbst mithilfe einer Zählervariablen manuell verfolgen. Das Problem besteht darin, dass es schwierig ist, zu kontrollieren, welche Teile Ihres Programms Speicher auf dem Heap zuweisen, insbesondere wenn Sie viele Bibliotheken verwenden, die sich Ihrer Kontrolle entziehen. Um die Sache noch komplizierter zu machen, gibt es zwei Möglichkeiten, wie ein Programm Heap-Speicher zuweisen kann:new
oder malloc
. (Ganz zu schweigen von direkten Betriebssystemaufrufen wie sbrk
.)
Sie können den globalen Operator new
überschreiben , und haben Sie jeden Aufruf zur neuen Erhöhung einer globalen Zählung. Dies schließt jedoch nicht unbedingt Zeiten ein, in denen Ihr Programm malloc
aufruft , oder wenn Ihr Programm einen klassenspezifischen new
verwendet überschreiben. Sie können auch malloc
überschreiben mit einem Makro, aber das ist nicht unbedingt portabel. Und Sie müssten auch alle Variationen von malloc
überschreiben , wie realloc
, calloc
usw. All dies wird durch die Tatsache weiter verkompliziert, dass bei einigen Implementierungen new
selbst kann malloc
aufrufen .
Im Grunde ist es also sehr schwierig, dies innerhalb Ihres Programms richtig zu tun. Ich würde stattdessen die Verwendung eines Speicherprofiler-Tools empfehlen.