web-dev-qa-db-fra.com

suivre les allocations de mémoire C ++

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?

47
BuschnicK

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++?".

7
BuschnicK

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:

  • QUI a alloué la mémoire (fonctions: g (), f () et main () dans l'exemple ci-dessus); vous obtenez également une trace complète menant à la fonction d'allocation,
  • à quelle structure de données la mémoire est allée (pas de structures de données dans l'exemple ci-dessus),
  • Quand c'est arrivé,
  • quel POURCENTAGE de toute la mémoire allouée c'est (g: 39,7%, f: 9,95%, principal: 49,7%).

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.

31
anon

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

  1. Fonctions de rapport d'état du tas
  2. Suivi des demandes d'allocation de tas . C'est probablement la fonctionnalité que vous recherchez.
19
Nitin Bhide

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
13
Skizz

Essayez aussi celui-ci: Validateur de mémoire

1
Naveen

Sur Mac OS X, vous pouvez utiliser l'outil de profilage de code Shark pour ce faire, IIRC.

0
paxos1977

"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). Memory block allocations over time

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.

0
araud

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é.

0
Totoro

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.

heap profiling

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.

0
gavinb