Comment détecter / éviter les fuites de mémoire dans votre code (non géré)? [fermé]

dans le code c/" class="blnk">C / C++ non géré, quelles sont les meilleures pratiques pour détecter les fuites de mémoire? Et des directives de codage à éviter? (Comme si c'est simple ;)

nous avons utilisé un peu d'une manière stupide dans le passé: avoir un contre-incrément pour chaque appel d'allocation de mémoire et décrément tout en libérant. À la fin du programme, la valeur du compteur devrait être zéro.

je sais que ce n'est pas un bon moyen et il y a quelques captures. (Par exemple, si vous êtes à la libérer mémoire qui a été attribuée par un appel API de plate-forme, votre nombre d'attribution ne correspond pas exactement à votre nombre de libération. Bien sûr, nous avons ensuite incrémenté le compteur en appelant des appels API qui allouaient de la mémoire.)

j'attends vos expériences, suggestions et peut-être quelques références à des outils qui simplifient cela.

122
demandé sur prakash 2008-09-05 16:18:00

29 réponses

si votre code c/c++ est portable à *nix, peu de choses sont meilleures que Valgrind .

77
répondu Jordi Bunster 2012-04-16 12:57:45

si vous utilisez Visual Studio, Microsoft fournit quelques fonctions utiles pour détecter et déboguer les fuites de mémoire.

je commencerais par cet article: https://msdn.microsoft.com/en-us/library/x98tx3cf (v=140).aspx

voici le résumé rapide de ces articles. Tout d'abord, inclure ces en-têtes:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

alors vous devez appeler ceci quand votre programme sort:

_CrtDumpMemoryLeaks();

alternativement, si votre programme ne sort pas au même endroit à chaque fois, vous pouvez l'appeler au début de votre programme:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

maintenant quand le programme sort toutes les allocations qui n'étaient pas libres seront imprimées dans la fenêtre de sortie avec le fichier dans lequel elles ont été attribuées et l'occurrence d'allocation.

Cette stratégie fonctionne pour la plupart des programmes. Toutefois, elle devient difficile ou impossible dans certains cas. cas. L'utilisation de bibliothèques tierces qui font une certaine initialisation au démarrage peut faire apparaître d'autres objets dans la mémoire dump et peut rendre difficile le traçage de vos fuites. En outre, si l'une de vos classes a des membres avec le même nom que l'une des routines d'allocation de mémoire( comme malloc), les macros de débogage CRT causeront des problèmes.

il y a d'autres techniques expliquées dans le lien MSDN mentionné ci-dessus qui pourraient aussi être utilisées.

64
répondu Dusty Campbell 2017-03-14 19:16:14

en C++: utiliser Rai. Pointeurs intelligents comme std::unique_ptr, std::shared_ptr, std::weak sont vos amis.

37
répondu Leon Timmermans 2016-11-24 15:40:46

en tant que développeur C++ voici quelques lignes directrices simples:

  1. N'utilisez des pointeurs qu'en cas d'absolue nécessité
  2. si vous avez besoin d'un pointeur, double vérifier si un SmartPointer est une possibilité
  3. Utilisation de la SAISIR Créateur modèle.

quant à la détection de fuites de mémoire personnellement, j'ai toujours utilisé détecteur visuel de fuites et le trouver très utile.

28
répondu Huppie 2008-09-05 12:26:42

J'utilise DevStudio depuis trop d'années maintenant et cela m'étonne toujours de voir combien de programmeurs ne connaissent pas les outils d'analyse de mémoire qui sont disponibles dans les bibliothèques de temps d'exécution de debug. Voici quelques liens pour commencer:

suivi des demandes d'attribution de tas - plus précisément la section sur les numéros de demande D'attribution uniques

_CrtSetDbgFlag

_CrtSetBreakAlloc

bien sûr, si vous n'utilisez pas DevStudio, cela ne sera pas particulièrement utile.

16
répondu Skizz 2016-01-14 11:28:11

je suis étonné que personne n'ait mentionné DebugDiag pour Windows OS.

Il fonctionne sur les constructions de publication, et même sur le site du client.

(Vous avez juste besoin de garder votre version de publication PDBs, et de configurer DebugDiag pour utiliser Microsoft public symbol server)

10
répondu Tal 2008-10-12 11:37:29

le détecteur de fuites visuel est un très bon outil, bien qu'il ne supporte pas les appels sur les durées D'exécution VC9 (MSVCR90D.DLL par exemple).

7
répondu Hernán 2008-12-22 23:19:33

Microsoft VC++ en mode debug montre des fuites de mémoire, bien qu'il ne montre pas où vos fuites sont.

si vous utilisez C++, vous pouvez toujours éviter d'utiliser New explicitement: vous avez vector , string , auto_ptr (pré C++11; remplacé par unique_ptr en C++11), unique_ptr (C++11) et shared_ptr (C++11) dans votre arsenal.

quand nouveau est inévitable, essayer de le cacher dans un constructeur (et cacher supprimer dans un destructeur); le même travaille pour des APIs tiers.

7
répondu Serge 2016-10-07 14:28:27

il y a plusieurs bibliothèques de remplacement" malloc " là-bas qui vous permettront d'appeler une fonction à la fin et il vous parlera de toute la mémoire non créée, et dans de nombreux cas, qui malloced (ou nouveau) il en premier lieu.

4
répondu Paul Tomblin 2008-09-05 12:22:51

si vous utilisez MS VC++, je recommande fortement cet outil gratuit du projet codeprojet: leakfinder de Jochen Kalmbach.

vous ajoutez simplement la classe à votre projet, et appelez

InitAllocCheck(ACOutput_XML)
DeInitAllocCheck()

avant et après le code vous voulez vérifier les fuites.

une fois que vous avez construit et lancé le code, Jochen fournit un outil GUI soigné où vous pouvez charger le résultat .xmlleaks fichier, et naviguer à travers la pile d'appels où chaque fuite a été générée pour traquer la ligne de code incriminée.

Rational's (Maintenant propriété D'IBM) PurifyPlus illustre les fuites de la même manière, mais je trouve l'outil leakfinder réellement plus facile à utiliser, avec le bonus de cela ne coûtant pas plusieurs milliers de dollars!

4
répondu John Sibly 2008-09-05 12:54:00

N'a jamais utilisé moi - même, mais mes amis C me disent purifier .

3
répondu Iain Holder 2008-09-05 12:22:31

si vous utilisez Visual Studio, il pourrait être intéressant de regarder limite de vérification . Ce n'est pas gratuit, mais ça a été incroyablement utile pour trouver des fuites dans mon code. Il ne fait pas seulement des fuites de mémoire non plus, mais aussi des fuites de ressources GDI, des erreurs D'utilisation de WinAPI, et d'autres choses. Il vous montrera même où la fuite de mémoire a été initialisée, ce qui le rend beaucoup plus facile de traquer la fuite.

3
répondu Herms 2008-09-05 12:50:16

je pense qu'il n'y a pas de réponse facile à cette question. La façon dont vous pourriez vraiment aborder cette solution dépend de vos exigences. Vous avez besoin d'une solution multi-plateforme? Utilisez-vous new/delete ou malloc/free (ou les deux)? Vous cherchez vraiment des "fuites" ou vous voulez une meilleure protection, comme détecter les dépassements de tampon (ou les sous-tirs)?

si vous travaillez du côté windows, les bibliothèques MS debug runtime ont une détection basique de debug fonctionnalité, et comme un autre l'a déjà souligné, il y a plusieurs enveloppes qui peuvent être incluses dans votre source pour aider à la détection des fuites. Trouver un paquet qui peut fonctionner avec new/delete et malloc/free Vous donne évidemment plus de flexibilité.

Je n'en sais pas assez sur le côté unix pour fournir de l'aide, bien que, encore une fois, d'autres l'aient fait.

mais au-delà de la détection de fuites, il y a la notion de détection de corruption de mémoire via des dépassements de tampon (ou vide). Ce type de fonctionnalité de débogage est je pense plus difficile que la simple détection de fuite. Ce type de système est aussi plus compliqué si vous travaillez avec des objets C++ parce que les classes polymorhpic peuvent être supprimées de différentes façons, ce qui provoque de la tricherie dans la détermination du pointeur de base vrai qui est supprimé. Je ne connais aucun bon système "libre" qui assure une protection convenable pour les dépassements. nous avons écrit un système (Cross platform) et l'avons trouvé assez difficile.

2
répondu Mark 2008-09-05 14:49:18

j'aimerais vous proposer quelque chose que j'ai utilisé par le passé: un vérificateur de fuites rudimentaire qui est au niveau des sources et assez automatique. Je donne ceci pour trois raisons:

  1. vous pourriez le trouver utile.

  2. bien que ce soit un peu krufty, Je ne laisse pas cela m'embarrasser.

  3. même si elle est liée à certains crochets win32, qui devrait être facile à atténuer.

il y a des choses dont vous devez être prudent lorsque vous l'utilisez: ne faites rien qui doit s'appuyer sur new dans le code sous-jacent, méfiez-vous des avertissements sur les cas où il pourrait manquer au sommet de leakcheck.cpp, réalisez que si vous activez (et corrigez tous les problèmes) le code qui fait le dumps d'image, vous pouvez générer un énorme fichier.

la conception est destinée à vous permettre d'allumer et d'éteindre le pion sans recompiler tout ce qui inclut son en-tête. Inclure leakcheck.h où vous voulez suivre la vérification et reconstruire une fois. Ensuite, compilez le leakcheck.cpp avec ou sans LEAKCHECK #defin'd Puis relink pour l'allumer et l'éteindre. Y compris unleakcheck.h s'éteindre localement dans un fichier. Deux macros sont fournies: CLEARALLOCINFO() évitera de rapporter le même fichier et line de façon inappropriée lorsque vous traversez un code d'allocation qui n'incluait pas leakcheck.H. ALLOCFENCE () laisse juste tomber une ligne dans le rapport généré, sans faire la répartition.

encore une fois, s'il vous plaît réaliser que je ne l'ai pas utilisé depuis un certain temps et vous pourriez avoir à travailler avec elle un peu. Je suis tomber dessus pour illustrer l'idée. S'il s'avère qu'il y a un intérêt suffisant, je serais prêt à travailler sur un exemple, mettre à jour le code dans le processus, et remplacer le contenu de L'URL suivante avec quelque chose de plus joli qui inclut une liste convenablement de couleur de syntaxe.

Vous pouvez le trouver ici: http://www.cse.ucsd.edu/~tkammeye/leakcheck.html

2
répondu Thomas Kammeyer 2008-09-05 17:31:04

Pour Linux: Essayez Google Perftools

Il ya beaucoup d'outils qui font similaire alloc/compte gratuit, les avantages de Goolge Perftools:

  • assez rapide (par rapport à valgrind: très rapide)
  • est livré avec un bel affichage graphique des résultats
  • a d'autres fonctionnalités utiles: profilage cpu, profilage mémoire-usage...
2
répondu Weidenrinde 2008-09-16 08:15:39

La meilleure défense contre les fuites est une structure de programme qui minimise l'utilisation de malloc. Cela est non seulement bon du point de vue de la programmation, mais améliore également la performance et la maintenabilité. Je ne parle pas d'utiliser d'autres choses à la place de malloc, mais en termes de réutiliser des objets et de garder des onglets très explicites sur tous les objets étant transmis autour plutôt que d'allouer à volonté comme on s'habitue souvent à dans les langues avec les éboueurs comme Java.

par exemple, un programme sur lequel je travaille a un tas d'objets frame représentant des données image. Chaque objet frame possède des sous-données, que le destructeur de frame libère. Le programme garde une liste de tous les cadres qui sont alloués, et quand il en a besoin d'un nouveau, vérifie une liste d'objets frame inutilisés pour voir s'il peut réutiliser un cadre existant plutôt que d'en allouer un nouveau. Lors de l'arrêt, il ne fait que passer en revue la liste, libérant tout.

2
répondu Dark Shikari 2008-09-16 08:22:26

je recommande d'utiliser validateur de mémoire du logiciel verify. Cet outil s'est avéré être d'une aide précieuse pour m'aider à dépister les fuites de mémoire et à améliorer la gestion de la mémoire des applications sur lesquelles je travaille.

un outil très complet et rapide.

2
répondu Fabien Hure 2008-09-21 12:59:27

comptez-vous les allocs et les frees en interpolant vos propres fonctions syscall qui enregistrent les appels et passent ensuite l'appel à la fonction réelle?

C'est la seule façon que vous pouvez garder la trace des appels provenant du code que vous n'avez pas écrit.

regardez la page de manuel de ld.alors? Or ld.alors?1 sur certains systèmes.

aussi faire Google LD_PRELOAD et vous trouverez des articles intéressants expliquant la technique sur www.itworld.com.

2
répondu Rob Wells 2012-07-03 14:14:55

au moins pour MS VC++, la bibliothèque D'exécution C a plusieurs fonctions que j'ai trouvées utiles dans le passé. Consultez L'aide MSDN pour les fonctions _Crt* .

1
répondu Dan Shield 2008-09-05 13:12:12

le mmgr de Paul Nettle est un de mes outils préférés de longue date. Vous incluez mmgr.h dans vos fichiers source, définissez TEST_MEMORY, et il délivre un fichier texte rempli de problèmes de mémoire qui se sont produits lors d'un lancement de votre application.

1
répondu Josh Matthews 2008-09-13 23:37:31

Générales De Codage De Ligne Directrice:

  • les ressources doivent être affectées à la même "couche" (Fonction/classe/bibliothèque) où elles sont affectées.
  • si ce n'est pas possible, essayez d'utiliser une désallocation automatique (boost shared pointer...)
1
répondu Weidenrinde 2008-09-16 08:17:48

les outils de débogage de mémoire valent leur pesant d'or, mais au fil des ans, j'ai découvert que deux idées simples peuvent être utilisées pour empêcher la plupart des fuites de mémoire/ressources d'être codées en premier lieu.

  1. écrivez le code de publication immédiatement après avoir écrit le code d'acquisition pour les ressources que vous voulez allouer. Avec cette méthode, il est plus difficile d '"oublier" et, dans un certain sens, oblige à penser sérieusement au cycle de vie des ressources utilisées l'avance au lieu de comme un de côté.

  2. utiliser le retour le plus sournoisement possible. Ce qui est alloué ne devrait être libéré qu'à un seul endroit si possible. Le cheminement conditionnel entre l'acquisition des ressources et la mise en liberté devrait être aussi simple et évident que possible.

1
répondu Einstein 2009-06-16 03:58:20

en haut de cette liste (quand je l'ai lu) était valgrind. Valgrind est excellent si vous êtes en mesure de reproduire la fuite sur un système d'essai. Je l'ai utilisé avec beaucoup de succès.

et si vous aviez remarqué que le système de production fuit en ce moment et que vous ne savez pas comment le reproduire en test? Les preuves de ce qui ne va pas sont saisies dans l'état de ce système de production, et il pourrait être suffisant de fournir un aperçu sur l'endroit où le problème est afin que vous pouvez de la reproduire.

C'est là que L'échantillonnage Monte Carlo entre en jeu. Lire L'article du blog de Raymond Chen, "La façon du pauvre homme d'identifier les fuites de mémoire "et puis vérifier mon implémentation (suppose Linux, testé seulement sur x86 et x86-64)

http://github.com/tialaramex/leakdice/tree/master

1
répondu tialaramex 2009-06-20 08:59:46

travaillant sur le système D'exploitation des téléphones cellulaires Motorola, nous avons détourné la bibliothèque d'allocation de mémoire pour observer toutes les allocations de mémoire. Il a aidé à trouver beaucoup de problèmes avec les allocations de mémoire. Puisque la prévention est mieux que la guérison, je recommande d'utiliser un outil d'analyse statique comme Klockwork ou PC-Lint

1
répondu aku 2010-10-12 02:58:00

Valgrind est une bonne option pour Linux. Sous MacOS X, vous pouvez activer la bibliothèque MallocDebug qui a plusieurs options pour déboguer les problèmes d'allocation de mémoire (voir la page de manuel malloc, la section "environnement" a les détails pertinents). Le SDK OS X inclut également un outil appelé MallocDebug (généralement installé dans / Developer/Applications/ Performance Tools/) qui peut vous aider à surveiller l'utilisation et les fuites.

0
répondu jbl 2008-09-05 14:42:50

Détecter:

Debug CRT

éviter:

pointeurs Intelligents, boehm GC

0
répondu DrPizza 2008-09-06 09:35:46

un bon malloc, calloc et reallloc remplacement est rmdebug, il est assez simple à utiliser. Il est beaucoup plus rapide de puis valgrind, de sorte que vous pouvez tester votre code en profondeur. Bien sûr, il a quelques inconvénients, une fois que vous avez trouvé une fuite, vous avez probablement encore besoin d'utiliser valgrind pour trouver où la fuite apparaît et vous ne pouvez tester mallocs que vous faites directement. Si un lib fuit parce que vous l'utilisez mal, rmdebug ne le trouvera pas.

http://www.hexco.de/rmdebug /

0
répondu quinmars 2008-10-12 12:17:38

la plupart des profileurs de mémoire ralentissent ma grande application Windows complexe au point où les résultats sont inutiles. Il y a un outil qui fonctionne bien pour trouver des fuites dans mon application: UMDH - http://msdn.microsoft.com/en-us/library/ff560206%28VS.85%29.aspx

0
répondu Sean 2010-12-02 22:48:41

Mtrace semble être le standard intégré pour linux. Les étapes sont:

  1. set up the environment variable MALLOC_TRACE in bash

    MALLOC_TRACE=/tmp/mtrace.dat

    export MALLOC_TRACE;
  2. ajouter # inclure vers le haut de votre fichier source principal
  3. Ajouter mtrace(); au début de main et muntrace (); au bas (avant la déclaration de retour)
  4. compilez votre programme avec le commutateur-g pour les informations de débogage
  5. exécuter votre programme
  6. afficher les informations de fuite avec

    mtrace your_prog_exe_name /tmp/mtrace.dat

    (J'ai d'abord dû installer le script mtrace perl sur mon système fedora avec yum installer glibc_utils )
-1
répondu paperhorse 2009-06-16 03:13:40