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


Функция 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 ноль, CommitSize ноль 64 страницы изначально зарезервированы для кучи. Одна страница изначально фиксируется.
ReserveSize ноль, CommitSize nonzero RtlCreateHeap задает ReserveSize равным CommitSize, а затем округляет ReserveSize до ближайшего нескольких (PAGE_SIZE * 16).
ReserveSize nonzero, CommitSize ноль Одна страница изначально фиксируется для кучи.
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 структуры параметров . Кучи также может потребоваться заполнить размер запроса для метаданных и выравнивания, чтобы запросы выделить блоки в пределах 4096 байт (1 страница) VirtualMemoryThreshold могут завершиться ошибкой, даже если максимальный размер кучи достаточно велик, чтобы содержать блок. (Дополнительные сведения о VirtualMemoryThresholdсм. в элементах параметра параметров для RtlCreateHeap.)

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

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

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

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

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

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

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

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

Заметка

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

Требования

Требование Ценность
минимальные поддерживаемые клиентские Windows XP
целевая платформа Всеобщий
заголовка ntifs.h (include Ntifs.h)
библиотеки Ntoskrnl.lib
DLL NtosKrnl.exe (режим ядра); Ntdll.dll (режим пользователя)
IRQL < DISPATCH_LEVEL

См. также

RtlAllocateHeap

RtlDeskHeap

RtlFreeHeap