!heap

L’extension !heap affiche les informations d’utilisation du tas, contrôle les points d’arrêt dans le gestionnaire de tas, détecte les blocs de tas qui ont été perdus, recherche les blocs de tas ou affiche des informations sur le tas de page.

Cette extension prend en charge le tas de segments et le tas NT. Utilisez !heap sans paramètre pour répertorier tous les tas et leur type.

!heap [HeapOptions] [ValidationOptions] [Heap] 
!heap -b [{alloc|realloc|free} [Tag]] [Heap | BreakAddress] 
!heap -B {alloc|realloc|free} [Heap | BreakAddress] 
!heap -l 
!heap -s [SummaryOptions] [StatHeapAddress] 
!heap -i HeapAddress
!heap -x [-v] Address 
!heap -p [PageHeapOptions] 
!heap -srch [Size] Pattern
!heap -flt FilterOptions
!heap -stat [-h Handle [-grp GroupBy [MaxDisplay]]]
!heap [-p] -?
!heap -triage [Handle | Address] 

Paramètres de segment et de tas NT

Ces paramètres fonctionnent avec les segments et les tas NT.

-s
Spécifie que les informations récapitulatives sont demandées. Si SummaryOptions et StatHeapAddress sont omis, les informations récapitulatives sont affichées pour tous les tas associés au processus actuel.

SummaryOptions
Cela peut être toute combinaison des options suivantes. Les SummaryOptions ne respectent pas la casse. Type !heap -s -? pour toute information supplémentaire.

Option Résultat

-v

Vérifie tous les blocs de données.

-bBucketSize

Spécifie la taille du compartiment. La valeur par défaut est 1024 bits.

-dDumpBlockSize

Spécifie la taille du compartiment.

-a

Vide tous les blocs de tas.

-c

Spécifie que le contenu de chaque bloc doit être affiché.

-triage [Handle|Address]
Provoque la recherche automatique des échecs dans les tas d’un processus par le débogueur. Si un handle de tas est spécifié en tant qu’argument, ce tas est examiné ; sinon, tous les tas sont recherchés pour un segment contenant l’adresse donnée, et s’il en est trouvé un, ce dernier est examiné. L’utilisation de -triage est la seule façon de valider l’altération du tas à faible fragmentation (LFH).

-x [-v]
Provoque la recherche du bloc de tas contenant l’adresse spécifiée. Si -v est ajouté, la commande recherche l’espace de mémoire virtuel entier du processus actuel pour rechercher des pointeurs vers ce bloc de tas.

-l
Provoque la détection des blocs de tas qui ont été perdus par le débogueur.

-iAddress-hHeapAddress
Affiche les informations du Heap spécifié.

Adresse
Cela spécifie l’adresse à rechercher.

-?
Affiche un court texte d’aide pour cette extension dans la fenêtre de commande de débogueur. Utilisez !heap -? pour l’aide générique, et !heap -p -? pour l’aide du tas de pages.

Paramètres de tas NT

Ces paramètres fonctionnent uniquement avec le tas NT.

HeapOptions
Cela peut être toute combinaison des options suivantes. Les valeurs HeapOptions sont sensibles à la casse.

Option Résultat

-v

Force le débogueur à valider le tas spécifié.

Remarque Cette option ne détecte pas l’altération du segment de fragmentation faible (LFH). Utilisez -triage à la place.

-a

Inclut dans l’affichage toutes les informations pour le tas spécifié. La taille, dans ce cas, est arrondie à la granularité du tas. (Exécution !heap avec l’option -a équivaut à l’exécuter avec les trois options -h -f -m, ce qui peut prendre beaucoup de temps).

-h

Inclut dans l’affichage toutes les entrées non LFH pour le tas spécifié.

-hl

Inclut dans l’affichage toutes les entrées, y compris les entrées LFH, pour le (s) tas spécifié (s).

-f

Inclut dans l’affichage toutes les entrées de liste libre pour le tas spécifié.

-m

Inclut dans l’affichage toutes les entrées de segment pour le tas spécifié.

-t

Inclut dans l’affichage les informations de balise pour le tas spécifié.

-T

Inclut dans l’affichage les entrées de pseudo-balise pour le tas spécifié.

-g

Inclut dans l’affichage les informations de balise globales. Les balises globales sont associées à chaque allocation non balisée.

-s

Inclut dans l’affichage des informations récapitulatives pour le tas spécifié.

-k

(cibles basées sur x86 uniquement) Inclut la trace de la pile associée à chaque entrée.

ValidationOptions
Peut être l’une des options suivantes. Les ValidationOptions sont sensibles à la casse.

Option Résultat

-D

Désactive la validation à l’appel pour le tas spécifié.

-E

Active la validation à l’appel pour le tas spécifié.

-d

Désactive la vérification du tas pour le tas spécifié.

-e

Active la vérification du tas pour le tas spécifié.

-iHeapAddressouHeapAddress
Affiche les informations du Heap spécifié.

BreakAddress
Spécifie l’adresse d’un bloc où un point d’arrêt doit être défini ou supprimé.

-b
Cela amène le débogueur à créer un point d’arrêt conditionnel dans le gestionnaire de tas. L’option -b peut être suivie par alloc, realloc ou free . Cela spécifie si le point d’arrêt sera activé en allouant, ré-allouant ou en libérant de la mémoire. Si BreakAddress est utilisé pour spécifier l’adresse du bloc, le type de point d’arrêt peut être omis. Si Heap est utilisé pour spécifier l’adresse du tas ou l’index du tas, le type doit être inclus, ainsi que le paramètre de Tag.

Graphique avec indicateur
Spécifie le nom de la balise dans le tas.

-B
Fait en sorte que le débogueur supprime un point d’arrêt conditionnel du gestionnaire de tas. Le type de point d’arrêt (alloc, realloc ou free) doit être spécifié et doit être le même que celui utilisé avec l’option -b.

StatHeapAddress
Spécifie l’adresse du tas. Si celle-ci est égale à 0 ou omise, tous les tas associés au processus en cours sont affichés.

-p
Spécifie que les informations de tas de pages sont demandées. S’il est utilisé sans pageHeapOptions, tous les segments de page sont affichés.

PageHeapOptions
Peut être l’une des options suivantes. Les PagesHeapOptions respectent la casse. Si aucune option n’est spécifiée, tous les handles de tas de pages possibles sont affichés.

Option Résultat

-hHandle

Fait en sorte que le débogueur affiche des informations détaillées sur un tas de page avec le handle Handle.

-aAddress

Fait en sorte que le débogueur trouve le tas de page dont le bloc contient Address. Les détails complets de la relation entre cette adresse et les blocs de tas de pages complètes seront inclus, par exemple si cette adresse fait partie d’un tas de pages, son décalage à l’intérieur du bloc et si le bloc est alloué ou a été libéré. Les traces de pile sont incluses chaque fois qu’elles sont disponibles. Lorsque vous utilisez cette option, la taille est affichée dans plusieurs des granularités d’allocation de tas.

-t[c|s] [Traces]

Fait en sorte que le débogueur affiche les traces collectées des utilisateurs de tas lourds. Traces spécifie le nombre de traces à afficher ; la valeur par défaut est 4. S’il existe plus de traces que le nombre spécifié, les traces les plus anciennes sont affichées. Si -t ou -tc sont utilisés, les traces sont triées par nombre d’utilisations. Si -ts est utilisé, les traces sont triées par taille. (Les options -tc et -ts sont uniquement prises en charge dans Windows XP. L’option -t est uniquement prise en charge dans Windows XP et les versions antérieures de Windows).

-fi [Traces]

Fait en sorte que le débogueur affiche les traces d’injection de fautes les plus récentes. Traces spécifie la quantité à afficher ; la valeur par défaut est 4.

-all

Fait en sorte que le débogueur affiche des informations détaillées sur tous les tas de page.

-?

Fait en sorte que le débogueur affiche l’aide de la page heap, y compris un diagramme des blocs de tas. (Ces diagrammes peuvent également être vus dans la section Remarques suivante).

Avant de pouvoir utiliser une commande d’extension !heap -p, la page heap doit être activée pour votre processus cible. Voir les détails dans la section Remarques suivante.

srch-
Analyse tous les tas pour le modèle donné.

Modèle
Spécifie un modèle à rechercher.

Taille
Peut être l’une des options suivantes. Cela spécifie la taille du modèle. Le ’-’ est requis.

Option Résultat

-b

Le modèle a une taille d’un octet.

-w

Le modèle a une taille de deux octets (un WORD).

-d

Le modèle a une taille de quatre octets (un DWORD).

-q

Le modèle a une taille de huit octets (un QWORD).

Si aucune des options ci-dessus n’est spécifiée, alors le modèle est supposé avoir la même taille que le pointeur machine.

-flt
Limite l’affichage pour inclure uniquement les tas avec la taille ou la plage de taille spécifiée.

FilterOptions
Peut être l’une des options suivantes. Les FilterOptions (options de filtre) sont sensibles à la casse.

Option Résultat

sSize

Limite l’affichage pour inclure uniquement les tas de la taille spécifiée.

rSizeMinSizeMax

Limite l’affichage pour inclure uniquement les tas dans la plage de taille spécifiée.

-stat
Affiche les statistiques d’utilisation pour le tas spécifié.

-hHandle
Fait en sorte que les statistiques d’utilisation ne concernent que le tas à Handle. Si Handle est égal à 0 ou omis, alors les statistiques d’utilisation pour tous les tas sont affichées.

-grpGroupBy
Réorganise l’affichage selon GroupBy. Les options pour GroupBy peuvent être trouvées dans le tableau suivant.

Option Résultat

A

Affiche les statistiques d’utilisation en fonction de la taille d’allocation.

B

Affiche les statistiques d’utilisation en fonction du nombre de blocs.

S

Affiche les statistiques d’utilisation en fonction de la taille totale de chaque allocation.

MaxDisplay
Limite la sortie à seulement le nombre de lignes MaxDisplay.

DLL

Windows XP et versions ultérieures

Ext.dll Exts.dll

Informations supplémentaires

Pour des informations sur les tas, veuillez consulter les ressources suivantes :

Livre : Microsoft Windows Internals (Au cœur de Windows de Mark Russinovich et David Salomon.

Exemple 11 : Activation de la vérification de la page heap

Exemple 12 : Utilisation de la vérification de la page heap pour trouver un bug

Pour des informations sur l’utilisation du journal des processus mémoire du tas, veuillez consulter l’exemple 11 : Démarrage d’une session de trace privée.

Notes

Cette commande d’extension peut être utilisée pour effectuer diverses tâches.

La commande d’extension standard !heap est utilisée pour afficher des informations sur le tas pour le processus en cours. (Cela ne doit être utilisé que pour les processus en mode utilisateur. La commande d’extension !pool devrait être utilisée pour les processus système).

Les commandes !heap -b et !heap -B sont utilisées pour créer et supprimer des points d’arrêt conditionnels dans le gestionnaire de tas.

La commande !heap -l détecte les blocs de tas non libérés. Elle utilise un algorithme de collecteur de déchets pour détecter tous les blocs occupés des tas qui ne sont référencés nulle part dans l’espace d’adresse du processus. Pour les applications volumineuses, cela peut prendre quelques minutes pour être complet. Cette commande n’est disponible que dans Windows XP et les versions ultérieures de Windows.

La commande !heap -x recherche un bloc de tas contenant une adresse donnée. Si l’option -v est utilisée, cette commande recherchera également dans l’espace mémoire virtuel entier du processus en cours des pointeurs vers ce bloc de tas. Cette commande n’est disponible que dans Windows XP et les versions ultérieures de Windows.

La commande !heap -p affiche diverses formes d’informations sur la page heap. Avant d’utiliser !heap -p, vous devez activer la page heap pour le processus cible. Cela se fait via l’utilitaire Global Flags (gflags.exe). Pour ce faire, lancez l’utilitaire, remplissez le nom de l’application cible dans la zone de texte Nom du fichier image, sélectionnez Options de fichier image et Activer la page heap, puis sélectionnez Appliquer. Vous pouvez également démarrer l’utilitaire Global Flags à partir d’une fenêtre de commande en saisissant gflags /ixxx.exe+hpa, où xxx.exe est le nom de l’application cible.

Les commandes !heap -p -t[c|s] ne sont pas prises en charge au-delà de Windows XP. Utilisez l’outil UMDH fourni avec le package de débogage pour obtenir des résultats similaires.

La commande !heap -srch affiche les entrées de tas qui contiennent un certain modèle spécifié.

La commande !heap -flt limite l’affichage aux seules allocations de tas d’une taille spécifiée.

La commande !heap -stat affiche les statistiques d’utilisation du tas.

Voici un exemple de la commande standard !heap :

0:000> !ntsdexts.heap -a
Index   Address  Name      Debugging options enabled
  1:   00250000 
    Segment at 00250000 to 00350000 (00056000 bytes committed)
    Flags:               50000062
    ForceFlags:          40000060
    Granularity:         8 bytes
    Segment Reserve:     00100000
    Segment Commit:      00004000
    DeCommit Block Thres:00000400
    DeCommit Total Thres:00002000
    Total Free Size:     000003be
    Max. Allocation Size:7ffddfff
    Lock Variable at:    00250b54
    Next TagIndex:       0012
    Maximum TagIndex:    07ff
    Tag Entries:         00350000
    PsuedoTag Entries:   00250548
    Virtual Alloc List:  00250050
    UCR FreeList:        002504d8
    128-bit bitmap of free lists
    FreeList Usage:      00000014 00000000 00000000 00000000
              Free    Free
              List    List
#       Head      Blink      Flink
    FreeList[ 00 ] at 002500b8: 002a4378 . 002a4378
                                0x02 - HEAP_ENTRY_EXTRA_PRESENT
                                0x04 - HEAP_ENTRY_FILL_PATTERN
        Entry     Prev    Cur   0x10 - HEAP_ENTRY_LAST_ENTRY

Address   Size    Size  flags
002a4370: 00098 . 01c90 [14] - free
    FreeList[ 02 ] at 002500c8: 0025cb30 . 002527b8
002527b0: 00058 . 00010 [04] - free
0025cb28: 00088 . 00010 [04] - free
    FreeList[ 04 ] at 002500d8: 00269a08 . 0026e530
0026e528: 00038 . 00020 [04] - free
0026a4d0: 00038 . 00020 [06] - free
0026f9b8: 00038 . 00020 [04] - free
0025cda0: 00030 . 00020 [06] - free
00272660: 00038 . 00020 [04] - free
0026ab60: 00038 . 00020 [06] - free
00269f20: 00038 . 00020 [06] - free
00299818: 00038 . 00020 [04] - free
0026c028: 00038 . 00020 [06] - free
00269a00: 00038 . 00020 [46] - free
 
    Segment00 at 00250b90:
Flags:           00000000
Base:            00250000
First Entry:     00250bc8
Last Entry:      00350000
Total Pages:     00000080
Total UnCommit:  00000055
Largest UnCommit:000aa000
UnCommitted Ranges: (1)
    002a6000: 000aa000

    Heap entries for Segment00 in Heap 250000
                        0x01 - HEAP_ENTRY_BUSY            
                        0x02 - HEAP_ENTRY_EXTRA_PRESENT   
                        0x04 - HEAP_ENTRY_FILL_PATTERN    
                        0x08 - HEAP_ENTRY_VIRTUAL_ALLOC   
                        0x10 - HEAP_ENTRY_LAST_ENTRY      
                        0x20 - HEAP_ENTRY_SETTABLE_FLAG1  
                        0x40 - HEAP_ENTRY_SETTABLE_FLAG2  
Entry     Prev    Cur   0x80 - HEAP_ENTRY_SETTABLE_FLAG3  

Address   Size    Size  flags       (Bytes used)    (Tag name)
00250000: 00000 . 00b90 [01] - busy (b90)
00250b90: 00b90 . 00038 [01] - busy (38) 
00250bc8: 00038 . 00040 [07] - busy (24), tail fill (NTDLL!LDR Database)
00250c08: 00040 . 00060 [07] - busy (48), tail fill (NTDLL!LDR Database)
00250c68: 00060 . 00028 [07] - busy (10), tail fill (NTDLL!LDR Database)
00250c90: 00028 . 00060 [07] - busy (48), tail fill (NTDLL!LDR Database)
00250cf0: 00060 . 00050 [07] - busy (38), tail fill (Objects=  80)
00250d40: 00050 . 00048 [07] - busy (2e), tail fill (NTDLL!LDR Database)
00250d88: 00048 . 00c10 [07] - busy (bf4), tail fill (Objects>1024)
00251998: 00c10 . 00030 [07] - busy (12), tail fill (NTDLL!LDR Database)
...
002525c0: 00030 . 00060 [07] - busy (48), tail fill (NTDLL!LDR Database)
00252620: 00060 . 00050 [07] - busy (38), tail fill (NTDLL!LDR Database)
00252670: 00050 . 00040 [07] - busy (22), tail fill (NTDLL!CSRSS Client)
002526b0: 00040 . 00040 [07] - busy (24), tail fill (Objects=  64)
002526f0: 00040 . 00040 [07] - busy (24), tail fill (Objects=  64)
00252730: 00040 . 00028 [07] - busy (10), tail fill (Objects=  40)
00252758: 00028 . 00058 [07] - busy (3c), tail fill (Objects=  88)
002527b0: 00058 . 00010 [04] free fill
002527c0: 00010 . 00058 [07] - busy (3c), tail fill (NTDLL!LDR Database)
00252818: 00058 . 002d0 [07] - busy (2b8), tail fill (Objects= 720)
00252ae8: 002d0 . 00330 [07] - busy (314), tail fill (Objects= 816)
00252e18: 00330 . 00330 [07] - busy (314), tail fill (Objects= 816)
00253148: 00330 . 002a8 [07] - busy (28c), tail fill (NTDLL!LocalAtom)
002533f0: 002a8 . 00030 [07] - busy (18), tail fill (NTDLL!LocalAtom)
00253420: 00030 . 00030 [07] - busy (18), tail fill (NTDLL!LocalAtom)
00253450: 00030 . 00098 [07] - busy (7c), tail fill (BASEDLL!LMEM)
002534e8: 00098 . 00060 [07] - busy (44), tail fill (BASEDLL!TMP)
00253548: 00060 . 00020 [07] - busy (1), tail fill (Objects=  32)
00253568: 00020 . 00028 [07] - busy (10), tail fill (Objects=  40)
00253590: 00028 . 00030 [07] - busy (16), tail fill (Objects=  48)
...
0025ccb8: 00038 . 00060 [07] - busy (48), tail fill (NTDLL!LDR Database)
0025cd18: 00060 . 00058 [07] - busy (3c), tail fill (NTDLL!LDR Database)
0025cd70: 00058 . 00030 [07] - busy (18), tail fill (NTDLL!LDR Database)
0025cda0: 00030 . 00020 [06] free fill (NTDLL!Temporary)
0025cdc0: 00020 . 00258 [07] - busy (23c), tail fill (Objects= 600)
0025d018: 00258 . 01018 [07] - busy (1000), tail fill (Objects>1024)
0025e030: 01018 . 00060 [07] - busy (48), tail fill (NTDLL!LDR Database)
...
002a4190: 00028 . 00118 [07] - busy (100), tail fill (BASEDLL!GMEM)
002a42a8: 00118 . 00030 [07] - busy (18), tail fill (Objects=  48)
002a42d8: 00030 . 00098 [07] - busy (7c), tail fill (Objects= 152)
002a4370: 00098 . 01c90 [14] free fill
002a6000:      000aa000      - uncommitted bytes.

Voici un exemple de la commande !heap -l :

1:0:011> !heap -l
1:Heap 00170000
Heap 00280000
Heap 00520000
Heap 00b50000
Heap 00c60000
Heap 01420000
Heap 01550000
Heap 016d0000
Heap 019b0000
Heap 01b40000
Scanning VM ...
## Entry     User      Heap      Segment       Size  PrevSize  Flags

001b2958  001b2960  00170000  00000000        40        18  busy extra
001b9cb0  001b9cb8  00170000  00000000        80       300  busy extra
001ba208  001ba210  00170000  00000000        80        78  busy extra
001cbc90  001cbc98  00170000  00000000        e0        48  busy extra
001cbd70  001cbd78  00170000  00000000        d8        e0  busy extra
001cbe90  001cbe98  00170000  00000000        68        48  busy extra
001cbef8  001cbf00  00170000  00000000        58        68  busy extra
001cc078  001cc080  00170000  00000000        f8       128  busy extra
001cc360  001cc368  00170000  00000000        80        50  busy extra
001cc3e0  001cc3e8  00170000  00000000        58        80  busy extra
001fe550  001fe558  00170000  00000000       150       278  busy extra
001fe6e8  001fe6f0  00170000  00000000        48        48  busy extra
002057a8  002057b0  00170000  00000000        58        58  busy extra
00205800  00205808  00170000  00000000        48        58  busy extra
002058b8  002058c0  00170000  00000000        58        70  busy extra
00205910  00205918  00170000  00000000        48        58  busy extra
00205958  00205960  00170000  00000000        90        48  busy extra
00246970  00246978  00170000  00000000        60        88  busy extra
00251168  00251170  00170000  00000000        78        d0  busy extra user_flag
00527730  00527738  00520000  00000000        40        40  busy extra
00527920  00527928  00520000  00000000        40        80  busy extra
21 leaks detected.

Le tableau de cet exemple contient les 21 fuites trouvées.

Voici un exemple de la commande !heap -x :

0:011> !heap 002057b8 -x
## Entry     User      Heap      Segment       Size  PrevSize  Flags

002057a8  002057b0  00170000  00170640        58        58  busy extra

Voici un exemple de la commande !heap -x -v :

1:0:011> !heap 002057b8 -x -v
## 1:Entry     User      Heap      Segment       Size  PrevSize  Flags

002057a8  002057b0  00170000  00170640        58        58  busy extra

Search VM for address range 002057a8 - 002057ff : 00205990 (002057d0),

Dans cet exemple, il y a un pointeur vers ce bloc de tas à l’adresse 0x00205990.

Voici un exemple de la commande !heap -flt s :

0:001>!heap -flt s 0x50

Cela affiche toutes les allocations de taille 0x50.

Voici un exemple de la commande !heap -flt r :

0:001>!heap -flt r 0x50 0x80

Cela affiche chaque allocation dont la taille est comprise entre 0x50 et 0x7F.

Voici un exemple de la commande !heap -srch.

0:001> !heap -srch 77176934
    _HEAP @ 00090000
   in HEAP_ENTRY: Size : Prev Flags - UserPtr UserSize - state
        00099A48: 0018 : 0005 [01] - 00099A50 (000000B8) - (busy)
          ole32!CALLFRAME_CACHE<INTERFACE_HELPER_CLSID>::`vftable'
    _HEAP @ 00090000
   in HEAP_ENTRY: Size : Prev Flags - UserPtr UserSize - state
        00099B58: 0018 : 0005 [01] - 00099B60 (000000B8) - (busy)
          ole32!CALLFRAME_CACHE<INTERFACE_HELPER_CLSID>::`vftable'

Les diagrammes suivants montrent l’agencement des blocs de tas.

Bloc de page légère -- alloué :

 +-----+---------------+---+                                  
 |     |               |   |                                  
 +-----+---------------+---+                                  
    ^         ^          ^                                    
    |         |          8 suffix bytes (filled with 0xA0)    
    |         User allocation (filled with E0 if zeroing not requested) 
    Block header (starts with 0xABCDAAAA and ends with 0xDCBAAAAA) 

Bloc de page légère -- libéré :

 +-----+---------------+---+                                  
 |     |               |   |                                  
 +-----+---------------+---+                                  
    ^         ^          ^                                    
    |         |          8 suffix bytes (filled with 0xA0)    
    |         User allocation (filled with F0 bytes)          
    Block header (starts with 0xABCDAAA9 and ends with 0xDCBAAA9) 

Bloc de page complet -- alloué :

 +-----+---------+---+-------                                 
 |     |         |   |  ... N/A page                          
 +-----+---------+---+-------                                 
    ^       ^      ^                                          
    |       |      0-7 suffix bytes (filled with 0xD0)        
    |       User allocation (if zeroing not requested, filled   
            with C0)       
    Block header (starts with 0xABCDBBBB and ends with 0xDCBABBBB) 

Bloc de page complet -- libéré :

 +-----+---------+---+-------                                 
 |     |         |   |  ... N/A page                          
 +-----+---------+---+-------                                 
    ^       ^      ^                                          
    |       |      0-7 suffix bytes (filled with 0xD0)        
    |       User allocation (filled with F0 bytes)            
    Block header (starts with 0xABCDBBA and ends with 0xDCBABBBA) 

Pour voir la trace de la pile de l’allocation ou de la libération d’un bloc de tas ou d’un bloc de page heap complet, utilisez dt DPH_BLOCK_INFORMATION avec l’adresse de l’en-tête, suivi de dds avec le champ StackTrace du bloc.