Сравнение методов выделения памяти

Выбор правильного метода выделения

Используйте следующее руководство, чтобы выбрать соответствующий API выделения памяти для вашего сценария:

Scenario Рекомендуемый API Примечания
Выделения C++ общего назначения new / std::make_unique / std::make_shared Выбор кода C++ по умолчанию. Внутренне использует кучу CRT. RAII обеспечивает автоматическую очистку.
Выделение C общего назначения malloc / calloc / realloc Выбор по умолчанию для кода C. Переносимые на разных платформах.
Выделение больше 1 МБ или требует элемента управления на уровне страницы VirtualAlloc Выделяется при детализации страниц (обычно 4 КБ). Используется для резервирования больших диапазонов адресов, страниц охранников или памяти с определенными атрибутами защиты (PAGE_READWRITE, PAGE_EXECUTE_READи т. д.).
Многие небольшие выделения с пользовательским элементом управления (например, распределитель пула) КучиAlloc / HeapCreate Создайте частную кучу для элемента управления изоляцией или сериализации. Используйте HEAP_NO_SERIALIZE только в том случае, если куча является исключительно однопоточной.
COM-взаимодействие (маршалированная память) CoTaskMemAlloc Требуется, когда память пересекает границы com-квартиры. Заглушки, созданные MIDL, используют CoTaskMemAlloc/CoTaskMemFree.
Устаревший код с помощью перемещаемой памяти GlobalAlloc / LocalAlloc Избегайте нового кода. Они добавляют дополнительные затраты на HeapAlloc и существуют в первую очередь для обратной совместимости с операциями буфера обмена и определенными API Win32, которые требуют их.

Important

Всегда правильно распределить пары и функции распределения сделки. Выделенная память должна HeapAlloc быть освобождена с помощью HeapFree —нет free() или LocalFree. Сочетание семей распределения и распределения сделки приводит к повреждению кучи, которая трудно диагностировать.

Note

VirtualAlloc vs HeapAlloc: VirtualAlloc работает с степенью детализации страницы (минимум 4 КБ, резервирования, выровненные по SYSTEM_INFO.dwAllocationGranularityсравнению с 64 КБ). Выделение большого количества небольших объектов с адресным пространством виртуальныхalloc. Используйте HeapAlloc (или malloc/new) для небольших частых выделений. Используйте VirtualAlloc, если необходимо зарезервировать большие области адресов, защиту страниц управления или реализовать пользовательские распределители.

Подробное сравнение

Ниже приведено краткое сравнение различных методов выделения памяти:

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

Начиная с 32-разрядной Windows, GlobalAlloc и LocalAlloc реализуются как функции-оболочки, которые вызывают HeapAlloc с помощью дескриптора кучи по умолчанию процесса. Таким образом, GlobalAlloc и LocalAlloc имеют больше накладных расходов, чем HeapAlloc.

Так как различные кучи распределители предоставляют отличительные функциональные возможности с помощью различных механизмов, необходимо освободить память с правильной функцией. Например, память, выделенная с помощью HeapAlloc , должна быть освобождена с помощью HeapFree , а не LocalFree или GlobalFree. Память, выделенная с помощью GlobalAlloc или LocalAlloc , должна запрашиваться, проверяться и выпускаться с соответствующей глобальной или локальной функцией.

Функция VirtualAlloc позволяет указать дополнительные параметры выделения памяти. Однако его выделение использует детализацию страницы, поэтому использование VirtualAlloc может привести к более высокому использованию памяти.

Функция malloc имеет недостаток зависимости от времени выполнения. Новый оператор имеет недостаток зависимости компилятора и зависимого языка.

Функция CoTaskMemAlloc имеет преимущество эффективной работы в C, C++или Visual Basic. Это также единственный способ совместного использования памяти в приложении на основе COM, так как MIDL использует CoTaskMemAlloc и CoTaskMemFree для маршалирования памяти.

Примеры

Глобальные и локальные функции

Функции кучи

Функции виртуальной памяти