!heap

A extensão !heap exibe informações de uso de heap, controla pontos de interrupção no gerenciador de heap, detecta blocos de heap vazados, procura blocos de heap ou exibe informações de heap de página.

Essa extensão dá suporte ao heap de segmento e ao heap NT. Use !heap sem parâmetro para listar todos os heaps e seus respectivos tipos.

!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 do heap de segmento e NT

Esses parâmetros funcionam com heaps de Segmento e NT.

-s
Especifica que as informações de resumo estão sendo solicitadas. Se SummaryOptions e StatHeapAddress forem omitidos, as informações de resumo serão exibidas para todos os heaps associados ao processo atual.

SummaryOptions
Pode ser qualquer combinação das opções a seguir. O parâmetro SummaryOptions não diferencia maiúsculas de minúsculas. Digite !heap -s -? para obter informações adicionais.

Opção Efeito

-v

Verifica todos os blocos de dados.

-b BucketSize

Especifica o tamanho do bucket. O padrão é 1024 bits.

-d DumpBlockSize

Especifica o tamanho do bucket.

-a

Despeja todos os blocos de heap.

-c

Especifica que o conteúdo de cada bloco deve ser exibido.

-triage [Manusear | Endereço]
Faz com que o depurador procure automaticamente falhas nos heaps de um processo. Se um identificador de heap for especificado como um argumento, esse heap será examinado. Caso contrário, haverá uma busca pelo endereço fornecido em todos os heaps e, se um heap for encontrado, ele será examinado. O uso de -triage é a única maneira de validar a corrupção de LFH (heap de baixa fragmentação).

-x [-v]
Faz com que o depurador procure o bloco de heap que contém o endereço especificado. Se -v for adicionado, o comando irá procurar ponteiros para esse bloco de heap em todo o espaço de memória virtual do processo atual.

-l
Faz com que o depurador detecte blocos de heap vazados.

-i Address -h HeapAddress
Exibe informações sobre o Heap especificado.

Endereço
Especifica o endereço a ser pesquisado.

-?
Exibe um pequeno texto de Ajuda dessa extensão na janela Comando do Depurador. Use !heap -? para ajuda genérica e !heap -p -? para ajuda de heap de página.

Parâmetros de heap NT

Esses parâmetros funcionam somente com o heap NT.

HeapOptions
Pode ser qualquer combinação das opções a seguir. Os valores de HeapOptions diferenciam maiúsculas de minúsculas.

Opção Efeito

-v

Faz com que o depurador valide o heap especificado.

Observação Essa opção não detecta corrupção de LFH (heap de baixa fragmentação). Para isso, use -triage.

-a

Faz com que a exibição inclua todas as informações do heap especificado. O tamanho, nesse caso, é arredondado para cima para a granularidade de heap. (Executar !heap com a opção -a é equivalente a executá-lo com as três opções -h -f -m, o que pode levar muito tempo.)

-h

Faz com que a exibição inclua todas as entradas não LFH para o heap especificado.

-hl

Faz com que a exibição inclua todas as entradas para os heaps especificados, incluindo entradas LFH.

-f

Faz com que a exibição inclua todas as entradas de lista livres para o heap especificado.

-m

Faz com que a exibição inclua todas as entradas de segmento para o heap especificado.

-t

Faz com que a exibição inclua as informações de marcação para o heap especificado.

-T

Faz com que a exibição inclua as entradas de pseudomarcação para o heap especificado.

-g

Faz com que a exibição inclua as informações de marcação global. As marcações globais são associadas a cada alocação não marcada.

-s

Faz com que a exibição inclua informações resumidas para o heap especificado.

-k

(Somente destinos baseados em x86) Faz com que a exibição inclua o backtrace de pilha associado a cada entrada.

ValidationOptions
Pode ser qualquer uma das opções a seguir. O parâmetro ValidationOptions diferencia maiúsculas de minúsculas.

Opção Efeito

-D

Desabilita a validação na chamada para o heap especificado.

-E

Habilita a validação na chamada para o heap especificado.

-d

Desabilita a verificação de heap para o heap especificado.

-e

Habilita a verificação de heap para o heap especificado.

-i Heap Address ou HeapAddress
Exibe informações sobre o Heap especificado.

BreakAddress
Especifica o endereço de um bloco onde um ponto de interrupção deve ser definido ou removido.

-b
Faz com que o depurador crie um ponto de interrupção condicional no gerenciador de heap. A opção -b pode ser seguida por alloc, realloc ou free, que especifica se o ponto de interrupção será ativado alocando, realocando ou liberando memória. Se BreakAddress for usado para especificar o endereço do bloco, o tipo de ponto de interrupção poderá ser omitido. Se Heap for usado para especificar o endereço do heap ou índice do heap, o tipo deverá ser incluído, bem como o parâmetro Tag.

Tag
Especifica o nome da marcação dentro do heap.

-B
Faz com que o depurador remova um ponto de interrupção condicional do gerenciador de heap. O tipo de ponto de interrupção (alloc, realloc ou free) deve ser especificado e deve ser o mesmo usado com a opção -b.

StatHeapAddress
Especifica o endereço do heap. Se for 0 ou omitido, todos os heaps associados ao processo atual serão exibidos.

-p
Especifica que as informações de heap de página estão sendo solicitadas. Se for usado sem PageHeapOptions, todos os heaps de página serão exibidos.

PageHeapOptions
Pode ser qualquer uma das opções a seguir. O parâmetro PageHeapOptions diferencia maiúsculas de minúsculas. Se nenhuma opção for especificada, todos os possíveis identificadores de heap de página serão exibidos.

Opção Efeito

-h Manusear

Faz com que o depurador exiba informações detalhadas sobre um heap de página com o identificador Handle.

-a Address

Faz com que o depurador localize o heap de página cujo bloco contém Address. Detalhes completos de como esse endereço se relaciona com os blocos de heap de página inteira serão incluídos, por exemplo, se esse endereço faz parte de um heap de página, seu deslocamento dentro do bloco e se o bloco foi alocado ou liberado. Os rastreamentos de pilha são incluídos sempre que disponíveis. Ao usar essa opção, o tamanho é exibido em múltiplos da granularidade de alocação de heap.

-t[c|s] [Traces]

Faz com que o depurador exiba os rastreamentos coletados dos usuários avançados de heap. Traces especifica o número de rastreamentos a serem exibidos; o padrão é quatro. Se houver mais rastreamentos do que o número especificado, os rastreamentos mais antigos serão exibidos. Se -t ou -tc for usado, os rastreamentos serão classificados por uso de contagem. Se -ts for usado, os rastreamentos serão classificados por tamanho. (As opções -tc e -ts são aceitas apenas no Windows XP; a opção -t é aceita apenas no Windows XP e em versões anteriores do Windows.)

-fi [Traços]

Faz com que o depurador exiba os rastreamentos de injeção de falha mais recentes. Traces especifica a quantidade a ser exibida; o padrão é 4.

-all

Faz com que o depurador exiba informações detalhadas sobre todos os heaps de página.

-?

Faz com que o depurador exiba a ajuda de heap de página, incluindo um diagrama de blocos de heap. (Esses diagramas também podem ser vistos na seção Comentários a seguir.)

Antes de usar qualquer comando de extensão !heap -p, o heap de página deve estar habilitado para o processo de destino. Veja os detalhes na seção Comentários a seguir.

-srch
Verifica todos os heaps para o padrão fornecido.

Padrão
Especifica um padrão pelo qual procurar.

Tamanho
Pode ser qualquer uma das opções a seguir. Isso especifica o tamanho do padrão. O "-" é obrigatório.

Opção Efeito

-b

O padrão de tamanho é um BYTE.

-w

O padrão de tamanho é um WORD.

-d

O padrão de tamanho é um DWORD.

-q

O padrão de tamanho é um QWORD.

Se nenhum dos itens acima for especificado, será assumido que o padrão é do mesmo tamanho que o ponteiro da máquina.

-flt
Limita a exibição para incluir apenas alocações heaps com o tamanho ou intervalo de tamanhos especificado.

FilterOptions
Pode ser qualquer uma das opções a seguir. O parâmetro FilterOptions diferencia minúsculas e maiúsculas.

Opção Efeito

s Tamanho

Limita a exibição para incluir apenas heaps de um único tamanho.

r SizeMin SizeMax

Limita a exibição para incluir apenas heaps dentro do intervalo de tamanhos especificado.

Observação

Em versões posteriores do !heap, as opções como -flt podem não estar mais presentes. Use a ajuda da linha de comando para confirmar as opções disponíveis.

-stat
Exibe estatísticas de uso para o heap especificado.

-h Manusear
Faz com que as estatísticas de uso somente do heap em Handle sejam exibidas. Se Handle for 0 ou omitido, as estatísticas de uso de todos os heaps serão exibidas.

-grp GroupBy
Reordena a exibição conforme especificado por GroupBy. As opções para GroupBy podem ser encontradas na tabela a seguir.

Opção Efeito

A

Exibe as estatísticas de uso de acordo com o tamanho da alocação.

B

Exibe as estatísticas de uso de acordo com a contagem de blocos.

S

Exibe as estatísticas de uso de acordo com o tamanho total de cada alocação.

MaxDisplay
Limita a saída a apenas o número de linhas de MaxDisplay.

DLL

Windows XP e versões posteriores

Ext.dll Exts.dll

Informações Adicionais

Para obter informações sobre heaps, confira os seguintes recursos:

Livro: Microsoft Windows Internals por Mark Russinovich e David Solomon.

Exemplo 11: Habilitando a verificação de heap de página

Exemplo 12: Usando a verificação de heap de página para localizar um bug

Para obter informações sobre como usar o registrador de processos de memória Heap, confira Exemplo 11: Iniciando uma sessão de rastreamento privado

Comentários

Esse comando de extensão pode ser usado para realizar diversas tarefas.

O comando !heap padrão é usado para exibir informações de heap do processo atual. (Isso deve ser usado apenas para processos do modo de usuário. O comando de extensão !pool deve ser usado para processos do sistema.)

Os comandos !heap -b e !heap -B são usados para criar e excluir pontos de interrupção condicionais no gerenciador de heap.

O comando !heap -l detecta blocos de heap vazados. Ele usa um algoritmo de coletor de lixo para detectar todos os blocos ocupados dos heaps que não são referenciados em lugar nenhum no espaço de endereço do processo. Em aplicativos grandes, pode levar alguns minutos para ser concluído. Esse comando está disponível apenas no Windows XP e versões posteriores do Windows.

O comando !heap -x procura um bloco de heap que contêm um determinado endereço. Se a opção -v for usada, esse comando também pesquisará todo o espaço de memória virtual do processo atual em busca de ponteiros para esse bloco de heap. Esse comando está disponível apenas no Windows XP e versões posteriores do Windows.

O comando !heap -p exibe várias formas de informações de heap de página. Antes de usar !heap -p, você deve habilitar o heap de página para o processo de destino. Isso é feito por meio do utilitário Sinalizadores Globais (gflags.exe). Para fazer isso, inicie o utilitário, preencha o nome do aplicativo de destino na caixa de texto Nome do Arquivo de Imagem, selecione Opções de Arquivo de Imagem, Habilitar heap de página e Aplicar. Como alternativa, é possível iniciar o utilitário Global Flags em uma janela de prompt de comando, digitando gflags /i xxx.exe +hpa, onde xxx.exe é o nome do aplicativo de destino.

Os comandos !heap -p -t[c|s] não são aceitos além do Windows XP. Use a ferramenta UMDH fornecida com o pacote do depurador para obter resultados semelhantes.

O comando !heap -srch exibe as entradas de heap que contêm um determinado padrão especificado.

O comando !heap -flt limita a exibição apenas a alocações de heap de um tamanho especificado.

O comando !heap -stat exibe estatísticas do uso de heap.

Veja a seguir um exemplo do comando !heap padrão:

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.

Veja a seguir um exemplo do comando !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.

A tabela neste exemplo contém todos os 21 vazamentos encontrados.

Veja a seguir um exemplo do comando !heap -x:

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

002057a8  002057b0  00170000  00170640        58        58  busy extra

Veja a seguir um exemplo do 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),

Neste exemplo, há um ponteiro para esse bloco de heap no endereço 0x00205990.

Veja a seguir um exemplo do comando !heap -flt s:

0:001>!heap -flt s 0x50

Isso exibirá todas as alocações de tamanho 0x50.

Veja a seguir um exemplo do comando !heap -flt r:

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

Isso exibirá cada alocação cujo tamanho está entre 0x50 e 0x7F.

Veja a seguir um exemplo do 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'

Os diagramas a seguir mostram a disposição dos blocos de heap.

Bloco de heap de página leve -- alocado:

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

Bloco de heap de página leve -- liberado:

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

Bloco de heap de página inteira -- alocado:

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

Bloco de heap de página inteira -- liberado:

 +-----+---------+---+-------                                 
 |     |         |   |  ... 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 o rastreamento de pilha da alocação ou a liberação de um bloco de heap ou bloco de heap de página inteira, use dt DPH_BLOCK_INFORMATION com o endereço de cabeçalho, seguido de dds com o campo StackTrace do bloco.