Что представляют собой разные столбцы в команде "! Heap -flt -s xxxx" - PullRequest
15 голосов
/ 14 июля 2011

Я работал над проблемами с высокой памятью, много занимался анализом кучи в windbg, и мне было любопытно, что на самом деле означают разные столбцы в команде "! Heap -flt -s xxxx",

Я прочитал Что означают числа 'size' в выводе windbg! Heap? , и я заглянул в свою книгу "Windows Internals", но у меня все еще оставалось множество вопросов.Таким образом, столбцы и мои вопросы ниже.

**HEAP_ENTRY** - What does this pointer really point to? How is it different than UserPtr?
**Size** - What does this size mean? How is it different than UserSize?
**Prev** - This just appears to be the negative offset to get to the previous heap entry. Still not sure exactly how it's used.
**Flags** - Is there any documentation on these flags?
**UserPtr** - What is the user pointer? In all cases I've seen it's always 8 bytes higher than the HEAP_ENTRY, but I don't really know what it points to.
**UserSize** - This appears to be the size of the actual allocation.
**state** - This just tells you what state of this heap entry is (free, busy, etc....)

Example:
HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
  0015eeb0 0044 0000  [07]   0015eeb8    00204 - (busy)

Ответы [ 3 ]

19 голосов
/ 09 августа 2011

HEAP_ENTRY Кучи хранят выделенные блоки в смежных сегментах памяти, каждый выделенный блок начинается с 8-байтового заголовка, за которым следуют фактические выделенные данные. Столбец HEAP_ENTRY - это адрес начала заголовка выделенного блока.

Размер Менеджер кучи обрабатывает блоки кратными 8 байтам. Столбец - это количество выделенного фрагмента из 8 байтов. В вашем примере 0044 означает, что блок занимает 0x220 байт (0x44 * 8).

Prev Умножьте на 8, чтобы иметь отрицательное смещение в байтах к предыдущему блоку кучи.

Флаги Это битовая маска, которая кодирует следующую информацию

0x01 - HEAP_ENTRY_BUSY
0x02 - HEAP_ENTRY_EXTRA_PRESENT
0x04 - HEAP_ENTRY_FILL_PATTERN
0x08 - HEAP_ENTRY_VIRTUAL_ALLOC
0x10 - HEAP_ENTRY_LAST_ENTRY

UserPtr Это указатель, возвращаемый приложению функцией HeapAlloc (вызывается функцией malloc / new). Поскольку заголовок всегда имеет длину 8 байт, он всегда равен HEAP_ENTRY + 8.

UserSize Это размер, переданный функции HeapAlloc.

состояние Это декодирование столбца Flags, указывающее, занята ли запись, освобождена ли она последним в своем сегменте,…

Имейте в виду, что в Windows 7/2008 R2 кучи по умолчанию используют интерфейс с именем LFH (Низко фрагментированная куча), который использует менеджер кучи по умолчанию для выделения фрагментов, в которых он отправлял данные, выделенные пользователем. Для этих куч, UserPtr и UserSize не будут указывать на реальные пользовательские данные. Вывод !heap -s показывает, какие кучи включены с LFH.

3 голосов
/ 02 августа 2011

Изучите документацию! Heap в файле справки средства отладки для Windows и документы кучи на MSDN и великолепный отрывок из Расширенная отладка Windows вот что я смог собрать:

  • HEAP_ENTRY : указатель на запись в куче. Как вы обнаружили, существует 8-байтовый заголовок, который содержит данные для структуры HEAP_ENTRY. Размер структуры HEAP_ENTRY составляет 8 байтов, что определяет размер «детализации кучи». Это используется для определения ...
  • РАЗМЕР : размер записи с точки зрения гранулярности (то есть размер распределения / 8)
  • FLAGS : они определены в winbase.h с объяснениями, найденными в MSDN ссылке.
  • USERPTR : фактический указатель на выделенный (или освобожденный) объект
0 голосов
/ 05 августа 2011

Ну, главное различие между HEAP_ENTRY и UserPtr заключается в том, что кучи должны быть проиндексированы, распределены, заполнены метаданными (например, выделенная длина сделана доступной пользователю) ... в противном случае, как вы могли бы освободиться ( р) что-то без указания, сколько байтов было выделено? То же самое с двумя полями размера: во-первых, насколько велика структура, индексирующая кучу, во-вторых, насколько велика область памяти, доступная для пользователя.

Флаги, в свою очередь, в основном указывают, какие свойства выделенного блока памяти, если он зафиксирован или просто зарезервирован, и, я полагаю, используются ядром для переупорядочения или совместного использования областей памяти, если это необходимо (но нифины указывают, что они задокументированы в MSDN).

PREV ptr используется для отслеживания всех выделенных областей, и первый указатель сохраняется в структуре PEB, так что как пользовательское пространство, так и код пространства ядра знают о выделенных пулах кучи.

...