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