Управление памятью в операционной системе WINDOWS, страница 12

Когда функция возвращает управление вызвавшей программе, структура MEMORY_BASIC_INFORMATION содержит базовый адрес выделенной области памяти, к которой принадлежит интересующий вас адрес (AllocationBase), текущий уровень защиты (Protect), уровень защиты, которым обладала страница в момент ее выделения (AllocationProtect), текущее состояние страницы (поле State может иметь одно из значений: MEM_FREE — свободная, MEM_RESERVE — зарезервированная или MEM_COMMIT — выделенная) и тип данных, хранящихся на странице (поле Type может иметь одно из значений: MEM_IMAGE — исполняемый код, MEM_MAPPED — файл, отображенный на память, MEM_PRIVATE — память принадлежит одному из процессов и не является памятью общего доступа). Структура также содержит адрес набора страниц (BaseAddress) и количество байт (RegionSize), которые обладают указанными атрибутами.

Использование исключений

При работе с памятью исключения — нередкая вещь. Исключения могут возникать при самых разных условиях, например, в случае, если произошло обращение по адресу за пределами массива, или в случае, если вы обратились к странице, обладающей атрибутом PAGE_GUARD. По умолчанию исключения обрабатываются операционной системой, однако вы можете включить в программу ваш собственный обработчик исключения. Windows ожидает, что вы будете обрабатывать исключение с использованием так называемой структурной обработки исключений (Structured Exception Handling, SEH), однако использовать SEH не очень удобно. Вместо этого компилятор С поддерживает конструкции _try и _except, облегчающие обработку исключений.

Стандартным средством обработки исключений в C++ являются ключевые слова try и catch. Эти операторы совместимы с объектной моделью C++. К сожалению, обработчики исключений C++ не понимают формат, в котором идентифицируются исключения Windows. К счастью, вы можете без труда написать простую функцию, которая осуществляет несложное преобразование формата идентификации исключений. Эта функция (возвращающая значение void) принимает код исключения и указатель на _EXCEPTION_POINTERS. Эти аргументы содержат всю необходимую информацию об исключении. Ваша задача — сгенерировать соответствующее исключение в формате C++.

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

void cppexcept( unsigned  int u, _EXCEPTION_ POINTERS* pExp )

( throw u;

}

Чтобы зарегистрировать эту функцию в качестве функции-преобразователя исключений, вы должны использовать вызов _set_se_translator. Этот вызоввозвращает указатель на предыдущую функцию-преобразователь. Этот указатель можно сохранить в переменной типа _se_translator_function для того, чтобы позже можно было восстановить функцию-преобразователь по умолчанию. Пример использования исключений приведен в листинге 3.

Создание дополнительного пула свободной памяти

Традиционно выделяемая программе память извлекается из пула свободной памяти, который называют кучей (heap). Обычно программа обладает собственной единственной кучей, которая используется при обращении к malloc или new. Однако в Windows можно создавать дополнительные кучи, которые будут использоваться одной и той же программой для получения новых участков памяти.) Для этого служит вызов HeapCreate. Этот вызов возвращает дескриптор новой кучи и принимает в качестве аргументов три значения: набор параметров, а также начальный и максимальный допустимый размеры кучи,                  1