Je cherche un moyen de suivre les allocations de mémoire dans un programme C++. Je ne suis pas intéressé par les fuites de mémoire, qui semblent être ce que la plupart des outils essaient de trouver, mais plutôt en créant un profil d'utilisation de la mémoire pour l'application. La sortie idéale serait soit une grande liste de noms de fonctions plus le nombre d'octets maximum alloués dans le temps, soit mieux encore, une représentation graphique du tas dans le temps. L'axe horizontal est le temps, l'espace de tas de l'axe vertical. Chaque fonction aurait sa propre couleur et tracerait des lignes en fonction des octets de tas alloués. Des points bonus pour identifier également les types d'objets attribués.
L'idée est de trouver des goulots d'étranglement de mémoire/pour visualiser quelles fonctions/threads consomment le plus de mémoire et devraient être ciblées pour une optimisation supplémentaire.
J'ai brièvement examiné Purify, BoundsChecker et AQTime mais ils ne semblent pas être ce que je recherche. Valgrind semble convenable, cependant, je suis sous Windows. Memtrack semble prometteur, mais nécessite des modifications importantes du code source.
Mes compétences Google doivent m'avoir échoué, car cela ne semble pas être une demande si rare? Toutes les informations nécessaires pour créer un outil comme celui-ci devraient être facilement disponibles à partir des symboles de débogage du programme ainsi que des appels d'API d'exécution - non?
Surveillance de l'utilisation de la mémoire de votre PC pour le développement de jeux contient un exemple presque parfait de ce que je cherchais. Il a fallu un certain temps pour le faire fonctionner, mais l'auteur de l'article a été très utile. Vous pouvez trouver le code source de l'outil ici Memtracer .
J'ai également reçu beaucoup de réponses utiles sur la SWENG (liste de diffusion en génie logiciel). Le thread est appelé "[Sweng-Gamedev] surveillant l'utilisation de la mémoire C++?".
Utilisez Valgrind et son outil Massif. Son exemple de sortie (une partie):
99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->49.74% (10,000B) 0x804841A: main (example.c:20)
|
->39.79% (8,000B) 0x80483C2: g (example.c:5)
| ->19.90% (4,000B) 0x80483E2: f (example.c:11)
| | ->19.90% (4,000B) 0x8048431: main (example.c:23)
| |
| ->19.90% (4,000B) 0x8048436: main (example.c:25)
|
->09.95% (2,000B) 0x80483DA: f (example.c:10)
->09.95% (2,000B) 0x8048431: main (example.c:23)
Ainsi, vous obtiendrez des informations détaillées:
Voici manuel Massif
Vous pouvez suivre l'allocation de tas ainsi que l'allocation de pile (désactivée par défaut).
PS. Je viens de lire que tu es sous Windows. Je laisserai cependant la réponse, car elle donne une image de ce que vous pouvez obtenir d'un outil possible.
Microsoft possède des fonctions de suivi de la mémoire bien documentées. Cependant, pour une raison quelconque, ils ne sont pas vraiment bien connus dans la communauté des développeurs. Ce sont des fonctions de débogage CRT. Un bon point de départ sera fonctions CRT Debug Heap .
Consultez les liens suivants pour plus de détails
Pour un traqueur de mémoire C++ générique, vous devrez surcharger les éléments suivants:
global operator new
global operator new []
global operator delete
global operator delete []
any class allocators
any in-place allocators
Le bit délicat obtient des informations utiles, les opérateurs surchargés n'ont que des informations de taille pour les allocateurs et des pointeurs de mémoire pour les suppressions. Une réponse consiste à utiliser des macros. Je sais. Méchant. Un exemple - placez dans un en-tête qui est inclus à partir de tous les fichiers source:
#undef new
void *operator new (size_t size, char *file, int line, char *function);
// other operators
#define new new (__FILE__, __LINE__, __FUNCTION__)
et créez un fichier source avec:
void *operator new (size_t size, char *file, int line, char *function)
{
// add tracking code here...
return malloc (size);
}
Ce qui précède ne fonctionne que si aucun opérateur nouveau n'est défini au niveau de la classe. Si vous en avez à portée de classe, faites:
#define NEW new (__FILE__, __LINE__, __FUNCTION__)
et remplacer "nouveau type" par "NOUVEAU type", mais cela nécessite potentiellement de modifier beaucoup de code.
Comme il s'agit d'une macro, la suppression du tracker de mémoire est assez simple, l'en-tête devient:
#if defined ENABLED_MEMORY_TRACKER
#undef new
void *operator new (size_t size, char *file, int line, char *function);
// other operators
#define NEW new (__FILE__, __LINE__, __FUNCTION__)
#else
#define NEW new
#endif
et le fichier d'implémentation:
#if defined ENABLED_MEMORY_TRACKER
void *operator new (size_t size, char *file, int line, char *function)
{
// add tracking code here...
return malloc (size);
}
endif
Essayez aussi celui-ci: Validateur de mémoire
Sur Mac OS X, vous pouvez utiliser l'outil de profilage de code Shark pour ce faire, IIRC.
"Une représentation graphique du tas au fil du temps" - proche de ce que vous recherchez est implémenté dans Intel (R) Single Event API , les détails peuvent être trouvés dans cet article (c'est assez gros pour le mettre ici).
Il vous montre la chronologie des allocations par taille de bloc et permet d'ajouter du balisage supplémentaire à votre code pour mieux comprendre l'ensemble de l'image.
Sur Xcode, vous pouvez utiliser Instruments pour suivre les allocations, VM, et plusieurs autres paramètres. Généralement populaire parmi les développeurs iOS, mais mérite d'être essayé.
Visual Studio IDE a un support de profilage de tas intégré (depuis 2015), qui est probablement le plus simple pour commencer. Il a des vues graphiques de l'utilisation du tas au fil du temps et peut suivre les allocations par fonction /méthode.
Le CRT a également un support de débogage et de profil, qui est plus détaillé et plus bas niveau. Vous pouvez suivre les données et tracer les résultats à l'aide d'un autre outil:
En particulier, regardez _CrtMemCheckpoint
et fonctions connexes.