Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows


Создание дополнительной кучи


Дополнительные кучи в процессе создаются вызовом HeapCreate

HANDLE HeapCreate( DWORD fdwOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize);

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

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

  1. Просматривает связанный список выделенных и свободных блоков памяти.
  2. Находит адрес свободного блока.
  3. Выделяет новый блок, помечая свободный как занятый.
  4. Добавляет новый элемент в связанный список блоков памяти.

Флаг HEAP_NO_SERIALIZE использовать нс следует, и вот почему. Допустим, два потока одновременно пытаются выделить блоки памяти из одной кучи. Первый по ток выполняет операции по пп 1 и 2 и получает адрес свободного блокз памяти. Но только он соберется перейти к третьему этапу, как сго вытеснит второй поток и тоже выполнит операции по пп. 1 и 2. Поскольку первый поток не успел дойти до этапа 3, второй поток обнаружит тот же свободный блок памяти,

Итак, оба потока считают, что они нашли свободный блок памяти в куче. Поэтому поток 1 обновляет связанный список, помечая новый блок как занятый. После этого и поток 2 обновляет связанный список, помечая тот же блок как занятый. Ни один из потоков пока ничего не подозревает, хотя оба получили адреса, указывающие на один и тот же блок памяти.

Ошибку такого рода обнаружить очень трудно, поскольку она проявляется не сра зу. Но в конце концов сбой произойдет и, будьте уверены, это случится в самый не подходящий момент, Вот какие проблемы это может вызвать.

  • Повреждение связанного списка блоков памяти. Эта проблема не проявится до попытки выделения или освобождения блока.

  • Оба потока делят один и тот же блок памяти. Оба записывают в него свою информацию Когда поток 1 начнет просматривать содержимое блока, он не поймет данные, записанные потоком 2.



  • Начало  Назад  Вперед



    Книжный магазин