HeapAlloc(…). Этот процесс состоит из следующих этапов.
1. проверки параметров функции HeapAlloc(…).
2. захват CriticalSection заголовка кучи.
3. выравнивание размера запрошенного блока к ближайшему числу кратному 4 и добавление размера арены. К каждому из 4-х списков относится запрошенный блок. 84 байта, 20h, 80h, 200h.
4. нахождение первого свободного блока в списке. Если блок найден, то функция проверяет насколько этот блок велик, нельзя ли его поделить на 2. Если можно, то создаются 2 блока, настраиваются их арены. Первый блок занят функцией HeapAlloc(…), другой поступает в список свободных блоков.
5. освобождение критической секции. Указатель кучи устанавливается на первый байт следующего за ареной блока. Если функция не найдёт в списке подходящего свободного блока, то kernel32 создаёт подкучу, настраивает её заголовок, вставляет подкучу в список подкуч, а затем функция HeapAlloc(…) возвращается к поиску свободных блоков.
HeapFree(…).
1. проверка параметров.
2. захват CriticalSection.
3. если перед освобождаемым блоком уже есть свободный блок, то они сливаются в один.
4. фактическое освобождение блока, возврат его в кучу.
5. освобождение CriticalSection.
освобождаемый блок
Перед HeapFree(…) стоит задача нахождения свободного блока. При освобождении блока в старших 4-х байтах свободного блока всегда записан адрес арены этого блока. Надо опуститься вниз на 4 байта и извлечь начало предыдущего блока.
Создаются по следующим причинам:
1. для защиты компонентов кучи.
2. для более эффективного управления памятью.
3. для локализации доступа.
Рассмотрим вариант 1. Пусть есть 2 потока:
Thread1 – Func1 – A
Thread2 – Func2 – B
куча
Имеется ошибка в программном коде Func1, которая приводит к тому, что после заполнения А1 записывается несколько дополнительных байт. Будут запорчены данные В3.
Программист сделает предположение, что ошибка в коде функции Func2. А если бы исполь-зовались 2 разные кучи, то локализовать ошибку легче.