Dans le code C / C ++ non managé, quelles sont les meilleures pratiques pour détecter les fuites de mémoire? Et les directives de codage à éviter? (Comme si c'était aussi simple que ça;)
Nous avons utilisé une méthode un peu stupide dans le passé: avoir un compteur incrémenté pour chaque appel d'allocation de mémoire et décrémenter lors de la libération. À la fin du programme, la valeur du compteur doit être zéro.
Je sais que ce n'est pas un excellent moyen et qu'il y a quelques prises. (Par exemple, si vous libérez de la mémoire qui a été allouée par un appel d'API de plate-forme, votre nombre d'allocations ne correspondra pas exactement à votre nombre de libérations. Bien sûr, nous avons incrémenté le compteur lors de l'appel des appels d'API qui ont alloué de la mémoire.)
J'attends vos expériences, suggestions et peut-être quelques références à des outils qui simplifient cela.
la source
Réponses:
Si votre code C / C ++ est portable vers * nix, peu de choses sont meilleures que Valgrind .
la source
Si vous utilisez Visual Studio, Microsoft fournit des 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=vs.140).aspx
Voici le résumé rapide de ces articles. Tout d'abord, incluez ces en-têtes:
Ensuite, vous devez appeler ceci lorsque votre programme se termine:
Alternativement, si votre programme ne se termine pas au même endroit à chaque fois, vous pouvez l'appeler au début de votre programme:
Désormais, lorsque le programme sortira, 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é allouées et l'occurrence d'allocation.
Cette stratégie fonctionne pour la plupart des programmes. Cependant, cela devient difficile voire impossible dans certains cas. L'utilisation de bibliothèques tierces qui effectuent une initialisation au démarrage peut entraîner l'apparition d'autres objets dans le vidage de la mémoire et rendre difficile le suivi 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 poseront des problèmes.
Il existe d'autres techniques expliquées dans le lien MSDN référencé ci-dessus qui pourraient également être utilisées.
la source
En C ++: utilisez RAII. Pointeurs intelligents comme
std::unique_ptr
,std::shared_ptr
,std::weak_ptr
sont vos amis.la source
En tant que développeur C ++, voici quelques directives simples:
En ce qui concerne la détection des fuites de mémoire personnellement, j'ai toujours utilisé Visual Leak Detector et je le trouve très utile.
la source
J'utilise DevStudio depuis bien trop d'années maintenant et je suis toujours étonné de voir combien de programmeurs ne connaissent pas les outils d'analyse de la mémoire disponibles dans les bibliothèques d'exécution de débogage. Voici quelques liens pour commencer:
Suivi des demandes d'allocation de tas - en particulier la section sur les numéros de demande d'allocation uniques
_CrtSetDbgFlag
_CrtSetBreakAlloc
Bien sûr, si vous n'utilisez pas DevStudio, cela ne sera pas particulièrement utile.
la source
Je suis étonné que personne n'ait mentionné DebugDiag pour Windows OS.
Cela fonctionne sur les versions de version, et même sur le site du client.
(Il vous suffit de conserver vos PDB de version de version et de configurer DebugDiag pour utiliser le serveur de symboles public Microsoft)
la source
Visual Leak Detector est un très bon outil, même s'il ne prend pas en charge les appels sur les runtimes VC9 (MSVCR90D.DLL par exemple).
la source
Microsoft VC ++ en mode débogage montre les fuites de mémoire, bien qu'il n'indique pas où se trouvent vos fuites.
Si vous utilisez C ++ , vous pouvez toujours éviter d' utiliser explicitement nouvelle: vous avez
vector
,string
,auto_ptr
(pré C ++ 11, remplacé parunique_ptr
en C ++ 11),unique_ptr
(C ++ 11) etshared_ptr
(C ++ 11) dans votre arsenal.Quand nouveau est inévitable, essayez de le cacher dans un constructeur (et de masquer la suppression dans un destructeur); la même chose fonctionne pour les API tierces.
la source
Il existe diverses bibliothèques de remplacement "malloc" qui vous permettront d'appeler une fonction à la fin et qui vous renseignera sur toute la mémoire non libérée, et dans de nombreux cas, qui l'a mallocée (ou créée) en premier lieu .
la source
Si vous utilisez MS VC ++, je vous recommande vivement cet outil gratuit du projet de code : leakfastinder de Jochen Kalmbach.
Vous ajoutez simplement la classe à votre projet et appelez
avant et après le code que vous souhaitez vérifier les fuites.
Une fois que vous avez créé et exécuté le code, Jochen fournit un outil graphique soigné dans lequel vous pouvez charger le fichier .xmlleaks résultant et naviguer dans la pile d'appels où chaque fuite a été générée pour rechercher la ligne de code incriminée.
PurifyPlus de Rational (maintenant détenu par IBM) illustre les fuites de la même manière, mais je trouve l'outil leakinder en fait plus facile à utiliser, avec l'avantage de ne pas coûter plusieurs milliers de dollars!
la source
Je ne l'ai jamais utilisé moi-même, mais mes amis C me disent Purify .
la source
Si vous utilisez Visual Studio, il peut être utile de consulter Bounds Checker . Ce n'est pas gratuit, mais cela a été incroyablement utile pour trouver des fuites dans mon code. Cela ne fait pas seulement des fuites de mémoire, mais aussi des fuites de ressources GDI, des erreurs d'utilisation de WinAPI et d'autres choses. Il vous montrera même où la mémoire divulguée a été initialisée, ce qui facilite grandement la recherche de la fuite.
la source
Je pense qu'il n'y a pas de réponse facile à cette question. La manière dont vous pourriez vraiment aborder cette solution dépend de vos besoins. Avez-vous besoin d'une solution multiplateforme? Utilisez-vous new / delete ou malloc / free (ou les deux)? Êtes-vous vraiment à la recherche de "fuites" ou voulez-vous une meilleure protection, comme la détection de dépassements de mémoire tampon (ou de sous-utilisation)?
Si vous travaillez du côté Windows, les bibliothèques d'exécution de débogage MS ont des fonctionnalités de détection de débogage de base, et comme un autre l'a déjà souligné, plusieurs wrappers peuvent être inclus dans votre source pour aider à la détection des fuites. Trouver un package qui peut fonctionner à la fois avec new / delete et malloc / free vous donne évidemment plus de flexibilité.
Je ne connais pas assez le côté Unix pour fournir de l'aide, même si, encore une fois, d'autres l'ont.
Mais au-delà de la simple détection de fuite, il y a la notion de détection de la corruption de la mémoire via des dépassements de tampon (ou des sous-exécutions). Ce type de fonctionnalité de débogage est, à mon avis, plus difficile que la simple détection de fuite. Ce type de système est également plus compliqué si vous travaillez avec des objets C ++ car les classes polymorhpiques peuvent être supprimées de différentes manières, ce qui complique la détermination du véritable pointeur de base à supprimer. Je ne connais aucun bon système «gratuit» qui assure une protection décente contre les dépassements. nous avons écrit un système (multiplateforme) et nous l'avons trouvé assez difficile.
la source
J'aimerais offrir quelque chose que j'ai parfois utilisé dans le passé: un vérificateur de fuite rudimentaire qui est au niveau de la source et assez automatique. Je donne cela pour trois raisons:
Vous pourriez trouver cela utile.
Bien que ce soit un peu krufty, je ne laisse pas cela me gêner.
Même s'il est lié à certains hooks win32, cela devrait être facile à atténuer.
Il y a des choses auxquelles vous devez faire attention lorsque vous l'utilisez: ne faites rien sur lequel vous devez vous appuyer
new
dans le code sous-jacent, méfiez-vous des avertissements sur les cas qu'il pourrait manquer en haut de leakcheck.cpp, réalisez que si vous activez sur (et résoudre tous les problèmes avec) le code qui effectue des vidages d'image, vous pouvez générer un fichier énorme.La conception est destinée à vous permettre d'activer et de désactiver le vérificateur sans recompiler tout ce qui comprend son en-tête. Incluez leakcheck.h où vous souhaitez suivre la vérification et reconstruire une fois. Ensuite, compilez le fichier leakcheck.cpp avec ou sans LEAKCHECK # défini, puis reliez-le pour l'activer et le désactiver. L'inclusion de unleakcheck.h le désactivera localement dans un fichier. Deux macros sont fournies: CLEARALLOCINFO () évitera de signaler le même fichier et la même ligne de manière inappropriée lorsque vous parcourez du code d'allocation qui n'inclut pas leakcheck.h. ALLOCFENCE () supprime simplement une ligne dans le rapport généré sans faire aucune allocation.
Encore une fois, sachez que je ne l'ai pas utilisé depuis un moment et que vous devrez peut-être travailler un peu avec. Je le dépose pour illustrer l'idée. S'il s'avère que l'intérêt est suffisant, je serais prêt à élaborer un exemple, à mettre à jour le code dans le processus et à remplacer le contenu de l'URL suivante par quelque chose de plus agréable comprenant une liste de syntaxe décemment colorée.
Vous pouvez le trouver ici: http://www.cse.ucsd.edu/~tkammeye/leakcheck.html
la source
Pour Linux: essayez Google Perftools
Il existe de nombreux outils qui font des allocations / comptages gratuits similaires, les avantages de Goolge Perftools:
la source
La meilleure défense contre les fuites est une structure de programme qui minimise l'utilisation de malloc. Ce n'est pas seulement bon du point de vue de la programmation, mais améliore également les performances et la maintenabilité. Je ne parle pas d'utiliser d'autres choses à la place de malloc, mais en termes de réutilisation des objets et de garder des onglets très explicites sur tous les objets en cours de transmission plutôt que d'allouer bon gré mal gré comme on s'habitue souvent dans les langues avec les ramasseurs d'ordures comme Java.
Par exemple, un programme sur lequel je travaille a un tas d'objets frame représentant des données d'image. Chaque objet frame a des sous-données, que le destructeur du frame libère. Le programme garde une liste de toutes les trames allouées, et quand il en a besoin d'une nouvelle, vérifie une liste d'objets de trame inutilisés pour voir s'il peut réutiliser une trame existante plutôt que d'en allouer une nouvelle. À l'arrêt, il itère simplement dans la liste, libérant tout.
la source
Je recommanderais d'utiliser Memory Validator partir de la vérification du logiciel. Cet outil s'est avéré être d'une aide précieuse pour m'aider à détecter 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.
la source
Comptez-vous les allocs et les libérations en interpolant vos propres fonctions syscall qui enregistrent les appels puis passent l'appel à la fonction réelle?
C'est la seule façon de garder une trace des appels provenant de code que vous n'avez pas écrit.
Jetez un œil à la page de manuel de ld.so. Ou ld.so.1 sur certains systèmes.
Faites également Google LD_PRELOAD et vous trouverez des articles intéressants expliquant la technique sur www.itworld.com.
la source
Au moins pour MS VC ++, la bibliothèque C Runtime a plusieurs fonctions que j'ai trouvées utiles dans le passé. Consultez l'aide MSDN pour les
_Crt*
fonctions.la source
Le mmgr de Paul Nettle est un de mes outils préférés depuis longtemps. Vous incluez mmgr.h dans vos fichiers source, définissez TEST_MEMORY et il fournit un fichier texte plein de problèmes de mémoire survenus lors de l'exécution de votre application.
la source
Directive générale de codage:
la source
Les outils de débogage de la 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.
Écrivez le code de version immédiatement après avoir écrit le code d'acquisition pour les ressources que vous souhaitez 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 plutôt que comme un aparté.
Utilisez le retour avec parcimonie. Ce qui est alloué ne doit être libéré qu'à un seul endroit si possible. Le chemin conditionnel entre l'acquisition des ressources et la libération doit être conçu pour être aussi simple et évident que possible.
la source
En haut de cette liste (quand je l'ai lu) se trouvait valgrind. Valgrind est excellent si vous êtes capable de reproduire la fuite sur un système de test. Je l'ai utilisé avec beaucoup de succès.
Et si vous venez de remarquer que le système de production fuit en ce moment et que vous ne savez pas comment le reproduire en test? Certaines preuves de ce qui ne va pas sont capturées dans l'état de ce système de production, et cela pourrait suffire à fournir un aperçu de l'emplacement du problème afin que vous puissiez le reproduire.
C'est là que l'échantillonnage Monte Carlo entre en scène. Lisez l'article du blog de Raymond Chen, «La manière du pauvre d'identifier les fuites de mémoire», puis consultez mon implémentation (suppose Linux, testé uniquement sur x86 et x86-64)
http://github.com/tialaramex/leakdice/tree/master
la source
En travaillant sur le système d'exploitation des téléphones portables Motorola, nous avons détourné la bibliothèque d'allocation de mémoire pour observer toutes les allocations de mémoire. Cela a aidé à trouver de nombreux problèmes d'allocation de mémoire. Étant donné que la prévention vaut mieux que le durcissement, je recommanderais d'utiliser un outil d'analyse statique comme Klockwork ou PC-Lint
la source
lint
. Il a de nombreux contrôles spécifiques au C ++, ce qu'afaik splint n'a pas. Voir le lien dans la réponse (que j'ai renommé de Lint en PC-Lint).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" contient les détails pertinents). Le SDK OS X comprend également un outil appelé MallocDebug (généralement installé dans / Developer / Applications / Performance Tools /) qui peut vous aider à surveiller l'utilisation et les fuites.
la source
Détecter:
Déboguer CRT
Éviter:
Pointeurs intelligents, boehm GC
la source
Un bon remplacement de malloc, calloc et reallloc est rmdebug, c'est assez simple à utiliser. Il est beaucoup plus rapide de valgrind, vous pouvez donc tester votre code de manière approfondie. Bien sûr, cela a quelques inconvénients, une fois que vous avez trouvé une fuite, vous devez probablement toujours utiliser valgrind pour trouver où la fuite apparaît et vous ne pouvez tester que les mallocs que vous faites directement. Si une bibliothèque fuit parce que vous l'utilisez mal, rmdebug ne la trouvera pas.
http://www.hexco.de/rmdebug/
la source
La plupart des profileurs de mémoire ralentissent ma grande application Windows complexe au point que les résultats sont inutiles. Il existe un outil qui fonctionne bien pour rechercher des fuites dans mon application: UMDH - http://msdn.microsoft.com/en-us/library/ff560206%28VS.85%29.aspx
la source
Mtrace semble être le standard intégré pour Linux. Les étapes sont:
MALLOC_TRACE = / tmp / mtrace.dat
export MALLOC_TRACE;
mtrace your_prog_exe_name /tmp/mtrace.dat
(j'ai d'abord dû installer le script perl mtrace sur mon système fedora avec yum install glibc_utils )
la source