Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпора 97.doc
Скачиваний:
0
Добавлен:
23.01.2020
Размер:
778.75 Кб
Скачать

7.1 Кучи

Win32 поддерживает области памяти в виде куч (heaps). Процесс может содержать несколько куч, и из них разработчик выделяет память.

Часто достаточно одной кучи, но по приведенным ниже причинам используется и много куч. Если достаточно одной кучи, просто используйте функции библиотеки С для управления памятью (malloc, free, calloc, realloc).

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

HANDLE GetProcessHeap (VOID)

Возвращаемое значение: дескриптор кучи процесса; NULL в случае неудачи.

Заметим, что в данном случае для указания на ошибку возвращается значение NULL, а не INVALID_HANDLE_VALUE, как в функции CreateFile.

Программа также может создавать особые кучи. Это относится к тем случаям, ко­гда необходимы отдельные кучи для резервирования отдельных структур данных. Ни­же описаны преимущества отдельных куч.

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

• Многопоточное быстродействие. Благодаря предоставлению каждому потоку от­дельной кучи соревнование между потоками сокращается, что может сущест­венно повысить быстродействие.

• Эффективность резервирования. Резервирование элементов данных фиксирован­ного размера в маленькой куче значительно более эффективно, чем резервиро­вание множества элементов разных размеров в одной большой куче. Также снижается фрагментация памяти. Кроме того, выделение каждому потоку от­дельной кучи упрощает синхронизацию, что дает дополнительный выигрыш.

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

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

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

Начальный размер кучи, который может быть нулевым и всегда округляется до числа, кратного размеру страницы, определяет объем физической памяти (в файле подкачки), первоначально отведенный куче. Когда программа выходит за границы начального размера, автоматически выделяются дополнительные страницы вплоть до максимального предела. Так как файл подкачки является ограниченным ресурсом, от­ложенное выделение удобно в случаях, когда размер кучи заранее не известен. Нену­левое значение переменной dwMaximumSize определяет предел для динамического повышения объема кучи. Куча процесса также будет динамически расти.

HANDLE HeapCreate ( DWORD flOptions,

SIZE_T dwInitialSize, SIZE_T dwMaximumSize);

Возвращаемое значение: дескриптор кучи или NULL в случае ошибки.

Два поля размера имеют тип size_t, а не dword. Тип size_t определен таким образом, что может быть 32-разрядным или 64-разрядным беззнаковым целым, в за­висимости от флагов компилятора (_WIN32 или _WIN64). Тип size_t был введен для обеспечения возможности перехода к WIN64.

Переменная flOptions является комбинацией двух флагов.

HEAP_GENERATE_EXCEPTIONS— при этом значении неудачные попытки выде­ления памяти вызывают исключения, которые будут обработаны структурным обработчиком исключений (Structured Exception Handler — SEH,). Функция HeapCreate сама по себе не вызывает исключений; если этот флаг ус­тановлен, исключение вызывают при неудаче такие функции, как HeapAlloc.

HEAP_NO_SERIALIZE — установка этого флага в некоторых случаях позволяет по­лучить небольшое повышение быстродействия. Следует сказать также несколько слов о dwMaximumSize.

• Если значение dwMaximumSize. не равно нулю, виртуальное адресное простран­ство выделяется и в том случае, когда весь указанный объем выделить невоз­можно. Это максимальный размер кучи, которая называется невозрастающей. Данная опция ограничивает размер кучи, возможно, для достижения справедли­вости распределения ресурсов, о которой упоминалось ранее.

• С другой стороны, если значение dwMaximumSize. — нуль, то куча является воз­растающей за пределы начального размера. Эта граница определяется доступ­ным виртуальным адресным пространством, часть которого может быть предос­тавлена другим кучам, и пространством файла подкачки.

Отметим, что кучи не имеют атрибутов безопасности, так как они недоступны из­вне процесса.

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

BOOL HeapDestroy (HANDLE hHeap);

Переменная hHeap должна указывать на кучу, созданную функцией HeapCreate. Будьте осторожны, не уничтожьте кучу процесса (полученную функцией GetProcessHeap). Уничтожение кучи освобождает пространство виртуальной памяти и физическую память в файле подкачки. Разумеется, грамотно спроектированные про­граммы должны освобождать кучи, которые больше не используются.

Уничтожение кучи — это также быстрый способ освободить структуру данных без необходимости уничтожать каждый элемент отдельно, хотя экземпляры объектов С++ таким образом не будут уничтожены, поскольку их деструкторы не вызываются. Уничтожение кучи имеет ряд преимуществ.

1. Нет необходимости писать код для поэлементного обхода структуры.

2. Нет необходимости освобождать каждый отдельный элемент.

3. Система не тратит время на поддержку кучи с того момента, когда все структу­ры данных освобождаются одним системным вызовом.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]