Что представляют собой разные столбцы в команде windbg "! Heap -flt -s xxxx"?
Я занимался некоторыми проблемами с высокой памятью, и я делал много анализа кучи в windbg, и мне было любопытно, что разные столбцы действительно означают в команде "! heap -flt -s xxxx",
Я читаю Что означают цифры "размер" в выводе windbg! heap?, и я смотрел в своей книге "Внутренние книги Windows", но у меня все еще было куча вопросов. Итак, столбцы и мои вопросы ниже.
**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 used.
**Flags** - Is there any documentation on these flags?
**UserPtr** - What is the user pointer? In all cases I've seen it 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)
Ответы
Ответ 1
HEAP_ENTRY
Храпы хранят выделенные блоки в смежных сегментах памяти, каждый выделенный блок начинается с 8-байтового заголовка, за которым следуют фактические выделенные данные. Столбец HEAP_ENTRY - это адрес начала заголовка выделенного блока.
Размер
Менеджер кучи обрабатывает блоки в количестве 8 байтов. Столбец - это количество выделенных 8 байтов. В вашем примере 0044 означает, что блок принимает 0x220 байт (0x44 * 8).
Prev
Умножьте на 8, чтобы иметь отрицательное смещение в байтах для предыдущего блока кучи.
Flags
Это битовая маска, которая кодирует следующую информацию.
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 (callbed by malloc/new). Поскольку заголовок всегда имеет длину 8 байтов, он всегда HEAP_ENTRY +8.
UserSize
Это размер, переданный функцией HeapAlloc.
состояние
Это расшифровка столбца "Флаги", указывающая, что запись занята, освобождена, последняя из ее сегмента,...
Помните, что в Windows 7/2008 R2 кучи по умолчанию используются в интерфейсе с именем LFH (низкоразделенная куча), который использует диспетчер кучи по умолчанию для выделения кусков, в которых он отправил данные, выделенные пользователем. Для этих кучек UserPtr и UserSize не будут указывать на реальные пользовательские данные.
Вывод !heap -s
показывает, какие кучи LFH включены.
Ответ 2
От взгляда на документацию! heap в файле справки отладки для Windows и в куче docs на MSDN и отличном отрывок из Расширенная отладка Windows, вот что мне удалось вместе:
- HEAP_ENTRY: указатель на запись в кучу. Как вы обнаружили, имеется 8-байтовый заголовок, который содержит данные для структуры HEAP_ENTRY. Размер структуры HEAP_ENTRY составляет 8 байтов, что определяет размер детализации "кучи". Это используется для определения...
- РАЗМЕР: размер записи с точки зрения детализации (т.е. размер размещения /8)
- FLAGS: они определены в winbase.h с объяснениями, найденными в MSDN.
- USERPTR: фактический указатель на выделенный (или освобожденный) объект
Ответ 3
Ну, основное различие между HEAP_ENTRY и UserPtr связано с тем, что кучи должны быть проиндексированы, выделены, заполнены метаданными (например, выделенная длина, предоставленная пользователю)... в противном случае, как вы могли бы освободить ( p) что-то, не указав, сколько байтов было выделено? То же самое с двумя полями размера: одна вещь - насколько велика структура, индексирующая кучу, одна вещь - насколько большой регион памяти, доступный пользователю.
FLAGS, в свою очередь, в основном определяют, какие свойства выделенного блока памяти, если он зафиксирован или просто зарезервирован, и, я полагаю, используется ядром для изменения или обмена областями памяти, если это необходимо (но поскольку нитхины указывают, что они задокументированы в MSDN).
PREV ptr используется для отслеживания всех выделенных областей, и первый указатель хранится в структуре PEB, так что код пространства пользователя и кода ядра знает о выделенных пулах кучи.