Поделиться через


!Кучи

Расширение !heap отображает сведения об использовании кучи, управляет точками останова в диспетчере куч, обнаруживает утечки блоков куч, ищет блоки кучи или отображает сведения о куче страницы.

Это расширение поддерживает кучу сегментов и кучу NT. Используйте !heap без параметра для перечисления всех кучи и их типа.

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

Параметры сегментов и кучи NT

Эти параметры работают с кучами сегментов и NT.

-s
Указывает, что запрашиваются сводные сведения. Если сводкаoptions и StatHeapAddress опущены, то для всех куч, связанных с текущим процессом, отображается сводная информация.

SummaryOptions
Может быть любым сочетанием следующих параметров. СводкаOptions не учитывает регистр. Тип !heap -s -? дополнительные сведения.

Вариант Действие

-v

Проверяет все блоки данных.

-bBucketSize

Указывает размер контейнера. Значение по умолчанию — 1024 бита.

-dDumpBlockSize

Указывает размер контейнера.

-a

Дамп всех блоков кучи.

-c

Указывает, что содержимое каждого блока должно отображаться.

-triage [Адрес дескриптора|]
Позволяет отладчику автоматически искать сбои в кучах процесса. Если дескриптор кучи указан в качестве аргумента, эта куча проверяется; в противном случае выполняется поиск всех куч, содержащих указанный адрес, и если он найден, он проверяется. Использование -triage — единственный способ проверить повреждение кучи с низкой фрагментацией (LFH).

-x [-v]
Позволяет отладчику искать блок кучи, содержащий указанный адрес. При добавлении -v команда будет выполнять поиск всего пространства виртуальной памяти текущего процесса для указателей на этот блок кучи.

-L
Позволяет отладчику обнаруживать утечки блоков куч.

-iAddress-h HeapAddress
Отображает сведения о указанной куче.

Адрес
Указывает адрес для поиска.

-?
Отображает краткий текст справки для этого расширения в окне команды отладчика. Используйте !heap -? для универсальной справки и !кучи -p -? для справки кучи страницы.

Параметры кучи NT

Эти параметры работают только с кучей NT.

HeapOptions
Может быть любым сочетанием следующих параметров. Значения HeapOptions чувствительны к регистру.

Вариант Действие

-v

Вызывает отладчик проверить указанную кучу.

Обратите внимание, что этот параметр не обнаруживает повреждение кучи с низкой фрагментацией (LFH). Вместо этого используйте -triage .

-a

Приводит к тому, что отображение будет содержать все сведения для указанной кучи. Размер, в данном случае, округляется до кучи детализации. (Запуск !кучи с параметром -a эквивалентен запуску с тремя параметрами -h -f -m, что может занять много времени.)

-h

Вызывает включение всех записей, отличных от LFH, для указанной кучи.

-Hl

Вызывает включение всех записей для указанных куч, включая записи LFH.

-f

Приводит к включению всех записей бесплатного списка для указанной кучи.

-m

Приводит к тому, что отображение включает все записи сегмента для указанной кучи.

-t

Вызывает включение сведений тега для указанной кучи.

-T

Приводит к включению записей псевдо тега для указанной кучы.

-g

Приводит к включению сведений о глобальном теге. Глобальные теги связаны с каждым выделением без тегов.

-s

Приводит к тому, что отображение содержит сводную информацию для указанной кучы.

-k

(только целевые объекты на основе x86) Приводит к включению стека обратного вывода, связанного с каждой записью.

ValidationOptions
Может быть одним из следующих вариантов. ПроверкаOptions учитывает регистр.

Вариант Действие

-D

Отключает проверку по вызову указанной кучы.

-E

Включает проверку по вызову указанной кучи.

-d

Отключает кучу проверка для указанной кучы.

-e

Включает кучи проверка для указанной кучи.

-iHeap AddressилиHeapAddress
Отображает сведения о указанной куче.

BreakAddress
Указывает адрес блока, в котором должна быть задана или удалена точка останова.

-b
Приводит отладчик к созданию условной точки останова в диспетчере куч. За параметром -b можно следовать распределить, переделать или освободить память. Это указывает, будет ли точка останова активирована путем выделения, перераспределения или освобождения памяти. Если BreakAddress используется для указания адреса блока, то тип точки останова может быть опущен. Если куча используется для указания адреса кучи или индекса кучи, необходимо включить тип, а также параметр Tag .

Тег
Указывает имя тега в куче.

-B
Позволяет отладчику удалить условную точку останова из диспетчера кучи. Тип точки останова (alloc, realloc или free) должен быть указан и должен быть таким же, как и для параметра -b .

StatHeapAddress
Указывает адрес кучи. Если это значение равно 0 или опущено, отображаются все кучи, связанные с текущим процессом.

-p
Указывает, что запрашиваются сведения о куче страниц. Если это используется без pageHeapOptions, будут отображаться все кучи страниц.

PageHeapOptions
Может быть одним из следующих вариантов. PageHeapOptions учитывает регистр. Если параметры не указаны, будут отображаться все возможные дескрипторы кучи страницы.

Вариант Действие

-hHandle

Позволяет отладчику отображать подробные сведения о кучи страницы с дескриптором дескриптора.

-aAddress

Позволяет отладчику найти кучу страницы, блок которой содержит адрес. Полные сведения о том, как этот адрес относится к блокам кучи полностраничных кучи, например, является ли этот адрес частью кучи страницы, ее смещением внутри блока, а также выделение или освобождение блока. Трассировки стека включаются всякий раз, когда они доступны. При использовании этого параметра размер отображается в нескольких фрагментах детализации распределения кучи.

-t[c|] [трассировки]

Позволяет отладчику отображать собранные трассировки тяжелых пользователей кучи. Трассировки указывают количество отображаемых трассировок; значение по умолчанию — четыре. Если существует больше трассировок, чем указанное число, отображаются самые ранние трассировки. Если используется функция -t или -tc , трассировки сортируются по количеству использования. Если используется -ts , трассировки сортируются по размеру. (Параметры -tc и -ts поддерживаются только в Windows XP; параметр -t поддерживается только в Windows XP и более ранних версиях Windows.)

-fi [трассировки]

Вызывает отладчик отображать последние трассировки внедрения ошибок. Трассировки указывают количество отображаемых значений; значение по умолчанию — 4.

-Все

Приводит к отображению отладчиком подробных сведений обо всех кучах страниц.

-?

Позволяет отладчику отображать справку кучи страницы, включая схему блоков кучи. (Эти схемы также можно увидеть в следующем разделе "Примечания".)

Прежде чем использовать любую команду расширения !heap -p , для целевого процесса необходимо включить кучу страницы. Дополнительные сведения см. в следующем разделе "Примечания".

-srch
Сканирует все кучы для заданного шаблона.

Шаблон
Указывает шаблон, для которого нужно выглядеть.

Размер
Может быть одним из следующих вариантов. Это указывает размер шаблона. Требуется значение "-".

Вариант Действие

-b

Шаблон — один РАЗМЕР BYTE.

-w

Шаблон — это один размер WORD.

-d

Шаблон — один DWORD в размере.

-q

Шаблон имеет один размер QWORD.

Если ни один из указанных выше не указан, предполагается, что шаблон имеет тот же размер, что и указатель компьютера.

-Flt
Ограничивает отображение только кучами с указанным размером или диапазоном размеров.

FilterOptions
Может быть одним из следующих вариантов. FilterOptions учитывает регистр.

Вариант Действие

Размер s

Ограничивает отображение только кучами указанного размера.

rSizeMinSizeMax

Ограничивает отображение только кучами в указанном диапазоне размеров.

-Стат
Отображает статистику использования для указанной кучы.

-hHandle
Приводит к отображению статистики использования только кучи при дескрипторе . Если дескриптор равен 0 или опущен, отображается статистика использования для всех кучи.

-grpGroupBy
Переупорядочение отображения, указанного GroupBy. Параметры GroupBy можно найти в следующей таблице.

Вариант Действие

Объект

Отображает статистику использования в соответствии с размером выделения.

B

Отображает статистику использования в соответствии с числом блоков.

S

Отображает статистику использования в соответствии с общим размером каждого выделения.

MaxDisplay
Ограничивает выходные данные только maxDisplay число строк.

DLL-библиотеки

Windows XP и более поздние версии

Ext.dll Exts.dll

Дополнительная информация

Дополнительные сведения о кучах см. в следующих ресурсах:

Книга: Внутренние компоненты Microsoft Windows Марк Руссинович и Дэвид Соломон.

Пример 11. Включение проверки кучи страниц

Пример 12. Использование проверки кучи страниц для поиска ошибки

Сведения об использовании средства ведения журнала обработки памяти кучи см . в примере 11. Запуск сеанса частной трассировки

Замечания

Эта команда расширения может использоваться для выполнения различных задач.

Стандартная команда !heap используется для отображения сведений о куче для текущего процесса. (Это должно использоваться только для процессов пользовательского режима. Команда расширения пула !pool должна использоваться для системных процессов.)

Команды !heap -b и !heap -B используются для создания и удаления условных точек останова в диспетчере кучи.

Команда !heap -l обнаруживает утечки блоков кучи. Он использует алгоритм сборщика мусора для обнаружения всех занятых блоков из куч, на которые нет ссылки в адресном пространстве процесса. Для огромных приложений может потребоваться несколько минут. Эта команда доступна только в Windows XP и более поздних версиях Windows.

Команда !heap -x ищет блок кучи, содержащий заданный адрес. Если используется параметр -v, эта команда будет дополнительно выполнять поиск всего пространства виртуальной памяти текущего процесса для указателей на этот блок кучи. Эта команда доступна только в Windows XP и более поздних версиях Windows.

Команда !heap -p отображает различные формы сведений о куче страницы. Перед использованием !heap -p необходимо включить кучу страниц для целевого процесса. Это делается с помощью программы глобальных флагов (gflags.exe). Для этого запустите служебную программу, введите имя целевого приложения в текстовом поле "Имя файла изображения", выберите "Параметры файла изображения" и "Включить кучу страницы" и нажмите кнопку "Применить". Кроме того, можно запустить служебную программу global Flags из окна командной строки, введя gflags /ixxx.exe+hpa, где xxx.exe — имя целевого приложения.

Команды !heap -p -t[c|s] не поддерживаются за пределами Windows XP. Используйте средство UMDH, предоставленное пакетом отладчика, чтобы получить аналогичные результаты.

Команда !heap -srch отображает эти записи кучи, содержащие определенный указанный шаблон.

Команда !heap -flt ограничивает отображение только выделения кучи указанного размера.

Команда !heap -stat отображает статистику использования кучи.

Ниже приведен пример стандартной команды !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.

Ниже приведен пример команды !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.

Таблица в этом примере содержит все 21 утечки.

Ниже приведен пример команды !heap -x :

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

002057a8  002057b0  00170000  00170640        58        58  busy extra

Ниже приведен пример команды !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),

В этом примере есть указатель на этот блок кучи по адресу 0x00205990.

Ниже приведен пример команды !heap -flt s :

0:001>!heap -flt s 0x50

При этом будут отображаться все выделения размера 0x50.

Ниже приведен пример команды !heap -flt r :

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

Будет отображаться каждое выделение, размер которого составляет от 0x50 до 0x7F.

Ниже приведен пример команды !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'

На следующих схемах показано расположение блоков кучи.

Блок кучи светлой страницы: выделено:

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

Блок кучи светлой страницы — освобожден:

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

Блокировка кучи полной страницы— выделена:

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

Полный блок кучи страницы — освобожден:

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

Чтобы просмотреть трассировку стека выделения или освобождения блока кучи или блока полной кучи страницы, используйте dt DPH_BLOCK_INFORMATION с адресом заголовка, а затем dds с полем StackTrace блока.