!heap

La extensión !heap muestra información sobre el uso del montón, controla los puntos de interrupción en el administrador de montón, detecta bloques de montón filtrados, busca bloques de montón o muestra información sobre el montón de la página.

Esta extensión admite el montón de segmento y el montón NT. Utilice !heap sin ningún parámetro para enumerar todos los montones y su tipo.

!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] 

Parámetros de montón de segmento y NT

Estos parámetros funcionan con los montones de Segmento y NT.

-s
Especifica que se está solicitando información resumida. Si se omiten SummaryOptions y StatHeapAddress, se mostrará información resumida de todos los montones asociados al proceso actual.

SummaryOptions
Puede ser combinación de las siguientes opciones. SummaryOptions no distingue entre mayúsculas y minúsculas. Escriba !heap -s -? para obtener información adicional.

Opción Efecto

-v

Verifica todos los bloques de datos.

-b BucketSize

Especifica el tamaño del cubo. El valor predeterminado es 1024 bits.

-d DumpBlockSize

Especifica el tamaño del cubo.

-a

Vuelca todos los bloques del montón.

-c

Especifica que se debe mostrar el contenido de cada bloque.

-triage [Handle | Address]
Hace que el depurador busque automáticamente errores en los montones de un proceso. Si se especifica un identificador de montón como argumento, se examina ese montón; de lo contrario, se buscan todos los montones en busca de uno que contenga la dirección determinada y, si se encuentra uno, se examina. El uso de -triage es la única forma de validar la corrupción del montón de baja fragmentación (LFH).

-x [-v]
Hace que el depurador busque el bloque de montón que contiene la dirección especificada. Si se añade -v, el comando buscará en todo el espacio de memoria virtual del proceso actual punteros a este bloque de montón.

-l
Hace que el depurador detecte los bloques de montón filtrados.

-i Address -h HeapAddress
Muestra información sobre el montón especificado.

Address
Especifica la dirección que se va a buscar.

-?
Muestra un breve texto de ayuda para esta extensión en la ventana de comando del depurador. Utilice !heap -? para ayuda genérica y !heap -p -? para ayuda del montón de páginas.

Parámetros del montón NT

Estos parámetros solo funcionan con el montón NT.

HeapOptions
Puede ser combinación de las siguientes opciones. Los valores de HeapOptions distinguen entre mayúsculas y minúsculas.

Opción Efecto

-v

Hace que el depurador valide el montón especificado.

Nota Esta opción no detecta la corrupción del montón de baja fragmentación (LFH). En su lugar, use -triage.

-a

Hace que la visualización incluya toda la información del montón especificado. El tamaño, en este caso, se redondea a la granularidad del montón. (Ejecutar !heap con la opción -a equivale a ejecutarlo con las tres opciones -h -f -m, lo que puede llevar mucho tiempo).

-h

Hace que la visualización incluya todas las entradas que no sean LFH para el montón especificado.

-hl

Hace que la visualización incluya todas las entradas del montón o montones especificados, incluidas las entradas LFH.

-f

Hace que la visualización incluya todas las entradas de la lista de libres para el montón especificado.

-m

Hace que la visualización incluya todas las entradas de segmento para el montón especificado.

-t

Hace que la visualización incluya la información de etiquetas del montón especificado.

-T

Hace que la visualización incluya las entradas de pseudoetiquetas del montón especificado.

-g

Hace que la visualización incluya la información de la etiqueta global. Las etiquetas globales se asocian a cada asignación no etiquetada.

-s

Hace que la visualización incluya información resumida del montón especificado.

-k

(Solo objetivos basados en x86) Hace que la visualización incluya el seguimiento regresivo de pila asociado a cada entrada.

ValidationOptions
Puede ser cualquiera de las siguientes opciones. ValidationOptions distingue entre mayúsculas y minúsculas.

Opción Efecto

-D

Deshabilita la validación en llamada para el montón especificado.

-E

Habilita la validación en llamada para el montón especificado.

-d

Deshabilita la comprobación para el montón especificado.

-e

Habilita la comprobación para el montón especificado.

-i Heap Address o HeapAddress
Muestra información sobre el montón especificado.

BreakAddress
Especifica la dirección de un bloque en el que se debe establecer o eliminar un punto de interrupción.

-b
Hace que el depurador cree un punto de interrupción condicional en el administrador de montón. La opción -b puede ir seguida de alloc, realloc, o free; esto especifica si el punto de ruptura se activará al asignar, reasignar o liberar memoria. Si se utiliza BreakAddress para especificar la dirección del bloque, se puede omitir el tipo de punto de ruptura. Si se utiliza Heap para especificar la dirección del montón o el índice del montón, debe incluirse el tipo, así como el parámetro Tag.

Tag
Especifica el nombre de la etiqueta dentro del montón.

-B
Hace que el depurador elimine un punto de interrupción condicional del administrador de montón. Debe especificarse el tipo de punto de ruptura (alloc, realloc, o free), que debe ser el mismo que el utilizado con la opción -b.

StatHeapAddress
Especifica la dirección del montón. Si es 0 o se omite, se mostrarán todos los montones asociados al proceso actual.

-p
Especifica que se está solicitando información sobre el montón de páginas. Si se utiliza sin ningún PageHeapOptions, se mostrarán todos los montones de páginas.

PageHeapOptions
Puede ser cualquiera de las siguientes opciones. PageHeapOptions distingue entre mayúsculas y minúsculas. Si no se especifica ninguna opción, se mostrarán todos los posibles identificadores del montón de páginas.

Opción Efecto

-h Handle

Hace que el depurador muestre información detallada sobre un montón de páginas con el identificador Handle.

-a Address

Hace que el depurador busque el montón de páginas cuyo bloque contiene Address. Se incluirán todos los detalles de cómo se relaciona esta dirección con los bloques del montón de páginas completas, como si esta dirección forma parte de un montón de páginas, su desplazamiento dentro del bloque y si el bloque está asignado o se liberó. Los seguimientos de pila se incluyen siempre que están disponibles. Cuando se utiliza esta opción, el tamaño se muestra en múltiplos de la granularidad de asignación del montón.

-t[c|s] [Traces]

Hace que el depurador muestre los seguimientos recopilados de los usuarios del montón pesado. Traces especifica el número de seguimientos que se va a mostrar; el valor predeterminado es cuatro. Si hay más seguimientos que el número especificado, se mostrarán los seguimientos más antiguos. Si se utiliza -t o -tc, los seguimientos se ordenan por uso de recuento. Si se utiliza -ts, los seguimientos se ordenan por tamaño. (Las opciones -tc y -ts solo son compatibles con Windows XP; la opción -t solo es compatible con Windows XP y versiones anteriores de Windows).

-fi [Traces]

Hace que el depurador muestre los seguimientos de inyección de errores más recientes. Traces especifica la cantidad que se va a mostrar; el valor predeterminado es 4.

-all

Hace que el depurador muestre información detallada sobre todos los montones de páginas.

-?

Hace que el depurador muestre la ayuda del montón de páginas, incluido un diagrama de los bloques de montón. (Estos diagramas también pueden verse en la siguiente sección de Observaciones).

Antes de que pueda utilizar cualquier comando de extensión !heap -p, el montón de páginas debe estar habilitado para su proceso de destino. Consulte los detalles en la siguiente sección de Observaciones.

-srch
Busca en todos los montones el patrón determinado.

Pattern
Especifica un patrón por el que buscar.

Size
Puede ser cualquiera de las siguientes opciones. Especifica el tamaño del patrón. El '-' es obligatorio.

Opción Efecto

-b

El patrón tiene un tamaño de un BYTE.

-w

El patrón tiene un tamaño de un WORD.

-d

El patrón tiene un tamaño de un DWORD.

-q

El patrón tiene un tamaño de un QWORD.

Si no se especifica ninguno de los anteriores, se supone que el patrón tiene el mismo tamaño que el puntero de la máquina.

-flt
Limita la visualización para incluir solo las asignaciones de montones con un tamaño o intervalo de tamaño especificado.

FilterOptions
Puede ser cualquiera de las siguientes opciones. FilterOptions distingue entre mayúsculas y minúsculas.

Opción Efecto

s Size

Limita la visualización para incluir solo los montones de un tamaño.

r SizeMin SizeMax

Limita la visualización para incluir solo los montones dentro del intervalo de tamaño especificado.

Nota:

En versiones posteriores de las opciones de !heap, como -flt puede que ya no estén presentes. Use la ayuda de la línea de comandos para confirmar las opciones disponibles.

-stat
Muestra las estadísticas de uso del montón especificado.

-h Handle
Hace que solo se muestren las estadísticas de uso del montón en Handle. Si Handle es 0 o se omite, se mostrarán las estadísticas de uso de todos los montones.

-grp GroupBy
Reordena la visualización según lo especificado por GroupBy. Las opciones de GroupBy se encuentran en la tabla siguiente.

Opción Efecto

A

Muestra las estadísticas de uso según el tamaño de la asignación.

B

Muestra las estadísticas de uso según el recuento de bloques.

S

Muestra las estadísticas de uso según el tamaño total de cada asignación.

MaxDisplay
Limita la salida a solo el número de líneas de MaxDisplay.

DLL

Windows XP y versiones posteriores

Ext.dll Exts.dll

Información adicional

Para obtener información sobre los montones, consulte los siguientes recursos:

Libro: Microsoft Windows Internals de Mark Russinovich y David Solomon.

Ejemplo 11: Habilitación de la verificación del montón de páginas

Ejemplo 12: Utilizar la verificación del montón de páginas para encontrar un error

Para obtener más información sobre el uso del registrador de procesos de memoria de montón, consulte Ejemplo 11: Iniciar una sesión privada de seguimiento

Comentarios

Este comando de extensión puede utilizarse para realizar diversas tareas.

El comando estándar !heap se utiliza para mostrar la información del montón del proceso actual. (Solo debe utilizarse para procesos en modo de usuario. El comando de extensión !pool debe utilizarse para los procesos del sistema).

Los comandos !heap -b y !heap -B se utilizan para crear y eliminar puntos de interrupción condicionales en el administrador del montón.

El comando !heap -l detecta los bloques de montón filtrados. Utiliza un algoritmo de recolección de basura para detectar todos los bloques ocupados de los montones a los que no se hace referencia en ninguna parte del espacio de direcciones del proceso. En el caso de solicitudes muy grandes, puede tardar unos minutos en completarse. Este comando solo está disponible en Windows XP y versiones posteriores de Windows.

El comando !heap -x busca un bloque de montón que contenga una dirección determinada. Si se usa la opción -v, este comando buscará además en todo el espacio de memoria virtual del proceso actual punteros a este bloque de montón. Este comando solo está disponible en Windows XP y versiones posteriores de Windows.

El comando !heap -p muestra varias formas de información sobre el montón de páginas. Antes de utilizar !heap -p, debe habilitar el montón de páginas para el proceso de destino. Esto se hace a través de la utilidad Global Flags (gflags.exe). Para ello, inicie la utilidad, rellene el nombre de la aplicación de destino en el cuadro de texto Image File Name (Nombre del archivo de imagen), seleccione Image File Options (Opciones de archivo de imagen) y Enable page heap (Habilitar montón de páginas),y seleccione Apply (Aplicar). Como alternativa, puede iniciar la utilidad Global Flags desde una ventana de símbolo del sistema escribiendo gflags /i xxx.exe +hpa, donde xxx.exe es el nombre de la aplicación de destino.

Los comandos !heap -p -t[c|s] no son compatibles más allá de Windows XP. Utilice la herramienta UMDH proporcionada con el paquete de depurador para obtener resultados similares.

El comando !heap -srch muestra las entradas del montón que contienen un determinado patrón especificado.

El comando !heap -flt limita la visualización a solo las asignaciones de montón de un tamaño especificado.

El comando !heap -stat muestra las estadísticas de uso del montón.

Este es un ejemplo de un comando !heap estándar:

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.

Este es un ejemplo de un comando !heap -I:

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.

La tabla de este ejemplo contiene las 21 fugas encontradas.

Este es un ejemplo de un comando !heap -x:

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

002057a8  002057b0  00170000  00170640        58        58  busy extra

Este es un ejemplo de un comando !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),

En este ejemplo, hay un puntero a este bloque de montón en la dirección 0x00205990.

Este es un ejemplo de un comando !heap -flt s:

0:001>!heap -flt s 0x50

Esto mostrará todas las asignaciones de tamaño 0x50.

Este es un ejemplo de un comando !heap -flt r:

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

Esto mostrará cada asignación cuyo tamaño esté entre 0x50 y 0x7F.

Este es un ejemplo de un comando !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'

Los siguientes diagramas muestran la disposición de los bloques de montón.

Bloque de montón de página ligera; asignado:

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

Bloque de montón de página ligera; libre:

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

Bloque de montón de página completa; asignado:

 +-----+---------+---+-------                                 
 |     |         |   |  ... 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) 

Bloque de montón de página completa; libre:

 +-----+---------+---+-------                                 
 |     |         |   |  ... 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) 

Para ver el rastro de pila de la asignación o la liberación de un bloque de montón o de un bloque de montón de página completa, utilice dt DPH_BLOCK_INFORMATION con la dirección de encabezado, seguido de dds con el campo StackTrace del bloque.