Prévention des fuites de mémoire dans les applications Windows

Plateformes affectées

Clients - Windows 7
Serveurs - Windows Server 2008 R2

Description

Les fuites de mémoire sont une classe de bogues où l’application ne parvient pas à libérer de la mémoire quand elle n’est plus nécessaire. Au fil du temps, les fuites de mémoire affectent les performances de l’application particulière ainsi que du système d’exploitation. Une fuite importante peut entraîner des temps de réponse inacceptables en raison d’une pagination excessive. Finalement, l’application ainsi que d’autres parties du système d’exploitation rencontreront des échecs.

Windows libère toute la mémoire allouée par l’application lors de l’arrêt du processus, de sorte que les applications à court terme n’affectent pas de manière significative les performances globales du système. Toutefois, les fuites dans des processus de longue durée tels que les services ou même les plug-ins Explorer peuvent avoir un impact considérable sur la fiabilité du système et peuvent forcer l’utilisateur à redémarrer Windows afin de rendre le système à nouveau utilisable.

Les applications peuvent allouer de la mémoire en leur nom par plusieurs moyens. Chaque type d’allocation peut entraîner une fuite s’il n’est pas libéré après utilisation. Voici quelques exemples de modèles d’allocation courants :

  • Mémoire de tas via la fonction HeapAlloc ou ses équivalents du runtime C/C++ malloc ou new
  • Allocations directes à partir du système d’exploitation via la fonction VirtualAlloc .
  • Les handles de noyau créés via les API Kernel32 telles que CreateFile, CreateEvent ou CreateThread, contiennent la mémoire du noyau au nom de l’application
  • Handles GDI et USER créés via les API User32 et Gdi32 (par défaut, chaque processus a un quota de 10 000 handles)

Bonnes pratiques

La surveillance de la consommation de ressources de votre application au fil du temps est la première étape de la détection et du diagnostic des fuites de mémoire. Utilisez le Gestionnaire des tâches Windows et ajoutez les colonnes suivantes : « Commit Size », « Handles », « User Objects » et « GDI Objects ». Cela vous permettra d’établir une base de référence pour votre application et de surveiller l’utilisation des ressources au fil du temps.

Capture d’écran montrant la page « Processus » dans le Gestionnaire des tâches Windows.

Les outils Microsoft suivants fournissent des informations plus détaillées et peuvent vous aider à détecter et diagnostiquer les fuites pour les différents types d’allocation dans votre application :

  • Analyseur de performances et Resource Monitor font partie de Windows 7 et peuvent surveiller et graphe l’utilisation des ressources au fil du temps
  • La dernière version d’Application Verifier peut diagnostiquer les fuites de tas sur Windows 7
  • L’UMDH, qui fait partie des outils de débogage pour Windows, analyse les allocations de mémoire du tas pour un processus donné et peut aider à trouver des fuites et d’autres modèles d’utilisation inhabituels
  • Xperf est un outil d’analyse des performances sophistiqué qui prend en charge les traces d’allocation de tas
  • Le tas de débogage CRT suit les allocations de tas et peut vous aider à créer vos propres fonctionnalités de débogage de tas

Certaines pratiques de codage et de conception peuvent limiter le nombre de fuites dans votre code.

  • Utilisez des pointeurs intelligents dans le code C++ pour les allocations de tas ainsi que pour les ressources Win32 telles que les HANDLEdu noyau. La bibliothèque C++ Standard fournit la classe auto_ptr pour les allocations de tas. Pour les autres types d’allocation, vous devez écrire vos propres classes. La bibliothèque ATL fournit un ensemble complet de classes pour la gestion automatique des ressources pour les objets de tas et les handles de noyau
  • Utilisez des fonctionnalités intrinsèques du compilateur telles que _com_ptr_t pour encapsuler vos pointeurs d’interface COM dans des « pointeurs intelligents » et faciliter le comptage des références. Il existe des classes similaires pour d’autres types de données COM : _bstr_t et _variant_t
  • Surveillez l’utilisation inhabituelle de la mémoire de votre code .NET. Le code managé n’est pas à l’abri des fuites de mémoire. Consultez « Suivi des fuites de mémoire managée » pour savoir comment trouver les fuites gc
  • Tenez compte des modèles de fuite dans le code côté client web. Les références circulaires entre des objets COM et des moteurs de script comme JScript peuvent provoquer de grandes fuites dans les applications web. « Comprendre et résoudre les modèles de fuite d’Internet Explorer » contient plus d’informations sur ces types de fuites. Vous pouvez utiliser le détecteur de fuites de mémoire JavaScript pour déboguer les fuites de mémoire dans votre code. Bien que Windows Internet Explorer 8, qui est fourni avec Windows 7, atténue la plupart de ces problèmes, les navigateurs plus anciens sont toujours vulnérables à ces bogues
  • Évitez d’utiliser plusieurs chemins de sortie d’une fonction. Les allocations attribuées aux variables à l’étendue de la fonction doivent être libérées dans un bloc particulier à la fin de la fonction
  • N’utilisez pas d’exceptions dans votre code sans libérer toutes les variables locales dans les fonctions. Si vous utilisez des exceptions natives, libérez toutes vos allocations à l’intérieur du bloc __finally. Si vous utilisez des exceptions C++, toutes vos allocations de tas et de gestion doivent être encapsulées dans des pointeurs intelligents
  • Ne pas ignorer ou réinitialiser un objet PROPVARIANT sans appeler la fonction PropVariantClear

Modèles d’allocation courants :

Outils Microsoft :

Liens supplémentaires :