Функция RtlCreateHeap (ntifs.h)

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

Синтаксис

NTSYSAPI PVOID RtlCreateHeap(
  [in]           ULONG                Flags,
  [in, optional] PVOID                HeapBase,
  [in, optional] SIZE_T               ReserveSize,
  [in, optional] SIZE_T               CommitSize,
  [in, optional] PVOID                Lock,
  [in, optional] PRTL_HEAP_PARAMETERS Parameters
);

Параметры

[in] Flags

Флаги, указывающие необязательные атрибуты кучи. Эти параметры влияют на последующий доступ к новой куче через вызовы функций кучи (RtlAllocateHeap и RtlFreeHeap).

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

Этот параметр может быть одним или несколькими из следующих значений.

Значение Значение
HEAP_GENERATE_EXCEPTIONS Указывает, что система будет указывать на сбой кучи, вызывая исключение, например STATUS_NO_MEMORY, вместо возврата NULL.
HEAP_GROWABLE Указывает, что куча может увеличиваться. Должен быть указан, если HeapBase имеет значение NULL.
HEAP_NO_SERIALIZE Указывает, что взаимное исключение не будет использоваться, когда функции кучи выделяют и освобождают память из этой кучи. Если HEAP_NO_SERIALIZE не указан, по умолчанию используется сериализация доступа к куче. Сериализация доступа к куче позволяет двум или более потокам одновременно выделять и освобождать память из одной кучи.

[in, optional] HeapBase

Задает одно из двух действий:

Если HeapBase имеет значение, отличное от NULL, он указывает базовый адрес для блока памяти, выделенной вызывающим объектом, который будет использоваться для кучи.

Если HeapBase имеет значение NULL, RtlCreateHeap выделяет системную память для кучи из виртуального адресного пространства процесса.

[in, optional] ReserveSize

Если Параметр ReserveSize является ненулевым значением, он указывает начальный объем памяти (в байтах), который необходимо зарезервировать для кучи. RtlCreateHeap округляет ReserveSize до следующей границы страницы, а затем резервирует блок этого размера для кучи.

Этот параметр является необязательным и может быть равен нулю. В следующей таблице описано взаимодействие параметров ReserveSize и CommitSize .

Значения Результат
ReserveSize zero, CommitSize zero 64 страницы изначально зарезервированы для кучи. Одна страница изначально фиксируется.
ReserveSize zero, CommitSize nonzero RtlCreateHeap задает значение ReserveSize равным CommitSize, а затем округляет Значение ReserveSize до ближайшего кратного значения (PAGE_SIZE * 16).
ReserveSize nonzero, CommitSize zero Одна страница изначально фиксируется для кучи.
ReserveSize nonzero, CommitSize nonzero Если параметр CommitSize больше, чем ReserveSize, RtlCreateHeap уменьшает значение CommitSize до ReserveSize.

[in, optional] CommitSize

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

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

[in, optional] Lock

Указатель на непрозрачную структуру ERESOURCE, используемую в качестве блокировки ресурса. Этот параметр является необязательным и может иметь значение NULL. При указании вызывающей стороны структура должна быть выделена из непагрегированного пула и инициализирована путем вызова ExInitializeResourceLite или ExReinitializeResourceLite. Если установлен флаг HEAP_NO_SERIALIZE, этот параметр должен иметь значение NULL.

[in, optional] Parameters

Указатель на структуру RTL_HEAP_PARAMETERS , содержащую параметры, применяемые при создании кучи. Этот параметр является необязательным и может иметь значение NULL.

Возвращаемое значение

RtlCreateHeap возвращает дескриптор для доступа к созданной куче.

Комментарии

RtlCreateHeap создает частный объект кучи, из которого вызывающий процесс может выделить блоки памяти путем вызова RtlAllocateHeap. Начальный размер фиксации определяет количество страниц, изначально выделенных для кучи. Начальный размер резерва определяет количество страниц, изначально зарезервированных для кучи. Зарезервированные, но незафиксированные страницы создают блок в виртуальном адресном пространстве процесса, в который можно развернуть кучу.

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

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

Кроме того, если куча не может быть обрастаема, возникает абсолютное ограничение: максимальный размер блока памяти в куче составляет 0x7F000 байтов. Пороговое значение виртуальной памяти кучи равно максимальному размеру блока кучи или значению элемента VirtualMemoryThreshold структуры Parameters в зависимости от того, что меньше. Куче также может потребоваться заполнить размер запроса для метаданных и выравнивания, поэтому запросы на выделение блоков в пределах 4096 байт (1 страница) VirtualMemoryThreshold могут завершиться ошибкой, даже если максимальный размер кучи достаточно велик, чтобы вместить блок. (Дополнительные сведения о VirtualMemoryThreshold см. в разделе Члены параметра Parameters для RtlCreateHeap.)

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

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

Система использует память из частной кучи для хранения структур поддержки кучи, поэтому не весь указанный размер кучи доступен для процесса. Например, если RtlAllocateHeap запрашивает 64 килобайта (K) из кучи с максимальным размером 64 КБ, запрос может завершиться ошибкой из-за системных издержек.

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

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

  • Процесс содержит только один поток.

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

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

Примечание

Чтобы защититься от нарушения доступа, используйте структурированную обработку исключений для защиты любого кода, который записывает в кучу или считывает из нее. Дополнительные сведения о структурированной обработке исключений с доступом к памяти см. в разделе Обработка исключений**.

Требования

Требование Значение
Минимальная версия клиента Windows XP
Целевая платформа Универсальное
Верхняя часть ntifs.h (включая Ntifs.h)
Библиотека Ntoskrnl.lib
DLL NtosKrnl.exe (режим ядра); Ntdll.dll (пользовательский режим)
IRQL < DISPATCH_LEVEL

См. также раздел

RtlAllocateHeap

RtlDe определенияheap

RtlFreeHeap