Utilisation de l’UMDH pour rechercher une fuite de mémoire User-Mode
L’utilitaire de tas de vidage en mode utilisateur (UMDH) fonctionne avec le système d’exploitation pour analyser les allocations de tas Windows pour un processus spécifique. L’UMDH localise la routine d’un processus spécifique qui fuit la mémoire.
L’UMDH est incluse dans outils de débogage pour Windows. Pour plus d’informations, consultez UMDH.
Préparation à l’utilisation de l’UMDH
Si vous n’avez pas encore déterminé le processus qui fuit la mémoire, commencez par le faire. Pour plus d’informations, consultez Utilisation de Analyseur de performances pour rechercher User-Mode fuites de mémoire.
Les données les plus importantes dans les journaux UMDH sont les traces de pile des allocations de tas. Pour déterminer si un processus fuit la mémoire du tas, analysez ces traces de pile.
Avant d’utiliser UMDH pour afficher les données de trace de pile, vous devez utiliser GFlags pour configurer correctement votre système. GFlags est inclus dans outils de débogage pour Windows.
Les paramètres GFlags suivants activent les traces de pile UMDH :
Dans l’interface graphique GFlags, choisissez l’onglet Fichier image, tapez le nom du processus (y compris l’extension de nom de fichier), appuyez sur la touche TAB, sélectionnez Créer une base de données de trace de pile en mode utilisateur, puis sélectionnez Appliquer.
Ou, de manière équivalente, utilisez la ligne de commande GFlags suivante, où ImageName est le nom du processus (y compris l’extension de nom de fichier) :
gflags /i ImageName +ust
Utilisez cette commande pour effacer les paramètres GFlag une fois que vous avez terminé. Pour plus d’informations, consultez Commandes GFlags.
gflags /i ImageName -ust
Par défaut, la quantité de données de trace de pile collectées par Windows est limitée à 32 Mo sur un processeur x86 et à 64 Mo sur un processeur x64. Si vous devez augmenter la taille de cette base de données, choisissez l’onglet Fichier image dans l’interface graphique GFlags, tapez le nom du processus, appuyez sur la touche TAB, case activée la zone de case activée Stack Backtrace (Megs), tapez une valeur (en Mo) dans la zone de texte associée, puis sélectionnez Appliquer. Augmentez cette base de données uniquement si nécessaire, car cela peut épuiser des ressources Windows limitées. Lorsque vous n’avez plus besoin de la plus grande taille, retournez ce paramètre à sa valeur d’origine.
Si vous avez modifié des indicateurs sous l’onglet Registre système , vous devez redémarrer Windows pour que ces modifications soient effectives. Si vous avez modifié des indicateurs sous l’onglet Fichier image , vous devez redémarrer le processus pour que les modifications soient effectives. Les modifications apportées à l’onglet Indicateurs de noyau prennent effet immédiatement, mais elles sont perdues lors du prochain redémarrage de Windows.
Avant d’utiliser UMDH, vous devez avoir accès aux symboles appropriés pour votre application. UMDH utilise le chemin de symbole spécifié par la variable d’environnement _NT_SYMBOL_PATH. Définissez cette variable sur un chemin contenant les symboles de votre application. Si vous incluez également un chemin d’accès aux symboles Windows, l’analyse peut être plus complète. La syntaxe de ce chemin de symbole est la même que celle utilisée par le débogueur ; Pour plus d’informations, consultez Chemin du symbole.
Par exemple, si les symboles de votre application se trouvent dans C:\MySymbols et que vous souhaitez utiliser le magasin de symboles Microsoft public pour vos symboles Windows, en utilisant C:\MyCache comme magasin en aval, vous devez utiliser la commande suivante pour définir le chemin de votre symbole :
set _NT_SYMBOL_PATH=c:\mysymbols;srv*c:\mycache*https://msdl.microsoft.com/download/symbols
En outre, pour garantir des résultats précis, vous devez désactiver la mise en cache BSTR. Pour ce faire, définissez la variable d’environnement OANOCACHE sur un (1). Définissez ce paramètre avant de lancer l’application dont les allocations doivent être tracées.
Si vous devez suivre les allocations effectuées par un service, vous devez définir OANOCACHE en tant que variable d’environnement système, puis redémarrer Windows pour que ce paramètre prenne effet.
Détection des augmentations des allocations de tas avec UMDH
Après avoir effectué ces préparations, vous pouvez utiliser UMDH pour capturer des informations sur les allocations de tas d’un processus. Pour ce faire, procédez comme suit :
Déterminez l’ID de processus (PID) du processus que vous souhaitez examiner.
Utilisez UMDH pour analyser les allocations de mémoire du tas pour ce processus et l’enregistrer dans un fichier journal. Utilisez le commutateur -p avec le PID et le commutateur -f avec le nom du fichier journal. Par exemple, si le PID est 124 et que vous souhaitez nommer le fichier journal Log1.txt, utilisez la commande suivante :
umdh -p:124 -f:log1.txt
Utilisez le Bloc-notes ou un autre programme pour ouvrir le fichier journal. Ce fichier contient la pile des appels pour chaque allocation de tas, le nombre d’allocations effectuées via cette pile d’appels et le nombre d’octets consommés via cette pile d’appels.
Étant donné que vous recherchez une fuite de mémoire, le contenu d’un seul fichier journal ne suffit pas. Vous devez comparer les fichiers journaux enregistrés à différents moments pour déterminer les allocations qui augmentent.
UMDH peut comparer deux fichiers journaux différents et afficher la modification de leurs tailles d’allocation respectives. Vous pouvez utiliser le symbole supérieur à (>) pour rediriger les résultats vers un troisième fichier texte. Vous pouvez également inclure l’option -d, qui convertit le nombre d’octets et d’allocations de l’hexadécimal en décimal. Par exemple, pour comparer Log1.txt et Log2.txt, en enregistrant les résultats de la comparaison dans le fichier LogCompare.txt, utilisez la commande suivante :
umdh log1.txt log2.txt > logcompare.txt
Ouvrez le fichier LogCompare.txt. Son contenu ressemble à ce qui suit :
+ 5320 ( f110 - 9df0) 3a allocs BackTrace00B53 Total increase == 5320
Pour chaque pile d’appels (intitulée « BackTrace ») dans les fichiers journaux UMDH, une comparaison est effectuée entre les deux fichiers journaux. Dans cet exemple, le premier fichier journal (Log1.txt) a enregistré 0x9DF0 octets alloués pour BackTrace00B53, tandis que le deuxième fichier journal a enregistré 0xF110 octets, ce qui signifie qu’il y avait 0x5320 octets supplémentaires alloués entre le moment où les deux journaux ont été capturés. Les octets provenaient de la pile des appels identifiée par BackTrace00B53.
Pour déterminer ce qui se trouve dans ce backtrace, ouvrez l’un des fichiers journaux d’origine (par exemple, Log2.txt) et recherchez « BackTrace00B53 ». Les résultats sont similaires à ces données :
00005320 bytes in 0x14 allocations (@ 0x00000428) by: BackTrace00B53 ntdll!RtlDebugAllocateHeap+0x000000FD ntdll!RtlAllocateHeapSlowly+0x0000005A ntdll!RtlAllocateHeap+0x00000808 MyApp!_heap_alloc_base+0x00000069 MyApp!_heap_alloc_dbg+0x000001A2 MyApp!_nh_malloc_dbg+0x00000023 MyApp!_nh_malloc+0x00000016 MyApp!operator new+0x0000000E MyApp!DisplayMyGraphics+0x0000001E MyApp!main+0x0000002C MyApp!mainCRTStartup+0x000000FC KERNEL32!BaseProcessStart+0x0000003D
Cette sortie UMDH montre qu’il y a eu 0x5320 (décimale 21280) octets totaux alloués à partir de la pile des appels. Ces octets ont été alloués à partir de 0x14 (décimale 20) d’allocations distinctes de 0x428 (1064 octets décimaux) chacune.
L’identificateur « BackTrace00B53 » est attribué à la pile des appels. Les appels de cette pile s’affichent. En examinant la pile des appels, vous voyez que la routine DisplayMyGraphics alloue de la mémoire via le nouvel opérateur, qui appelle la routine malloc, qui utilise la bibliothèque runtime Visual C++ pour obtenir de la mémoire à partir du tas.
Déterminez lequel de ces appels est le dernier à apparaître explicitement dans votre code source. Dans ce cas, il s’agit probablement du nouvel opérateur, car l’appel à malloc s’est produit dans le cadre de l’implémentation de new plutôt que dans le cadre d’une allocation distincte. Ainsi, cette instance du nouvel opérateur dans la routine DisplayMyGraphics alloue à plusieurs reprises de la mémoire qui n’est pas libérée.