Программа-пример Spreadsheet
Этя программа, «25 Spreadsheet.exe» (см. листинг на рис. 25-1), демонстрирует, как передавать физическую память зарезервированному региону адресного простран ства — но не всему региону, а только его областям, нужным в данный момент. Алго ритм опирается на структурную обработку исключений. Файлы исходного кода и ре сурсов этой программы находятся в каталоге 25-Spreadshect на компакт-диске, при лагаемом к книге. После запуска Spreadsheet на экране появляется диалоговое окно, показанное ниже.
Программа Spreadsheet резервирует регион для двухмерной таблицы, содержащей 256 строк и 1024 колонки, с размером ячеек по 1024 байта Если бы программа за ранее передавала физическую память под всю таблицу, то ей понадобилось бы 268 435 456 байтов, или 256 Мб. Поэтому для экономии драгоценных ресурсов про грамма резервирует в своем адресном пространстве регион размером 256 Мб, нс пе редавая ему физическую память.
Допустим, пользователь хочет поместить значение 12345 в ячейку на пересечении строки 100 и колонки 100 (как на предыдущей иллюстрации) Кактолько он щелкнет кнопку Write Cell, программа попытается записать это значение в указанную ячейку таблицы. Естественно, это вызовет нарушение доступа. Но, так как я использую в про грамме SEH, мой фильтр исключений, распознав попытку записи, выведет в нижней части диалогового окна сообщение «Violation: Attempting to Write», передаст память под нужную ячейку и заставит процессор повторить выполнение команды, возбудив шей исключение Теперь значение будет сохранено в ячсйкс таблицы, поскольку этой ячейке нередана физическая память.
Проделаем еще один эксперимент. Попробуем считать значение из ячейки на пересечении строки 5 и колонки 20 Этим мы вновь вызовем нарушение доступа. На этот раз фильтр исключений не передаст память, а выведет в диалоговом окне сооб щение «Violation: Attempting to Read». Программа корректно возобновит свою работу после неудавшейся попытки чтения, очистив поле Value диалогового окна.
Третий эксперимент: попробуем считать значение из ячейки на пересечении стро ки 100 и колонки 100. Так как этой ячейке передана физическая память, никаких ис ключений не возбуждается, и фильтр не выполняется (что положительно сказывается на быстродействии программы). Диалоговое окно будет выглядеть следующим об разом.
Ну и последний эксперимент запишем значение 54321 в ячейку на пересечении строки 100 и колонки 101 Эта операция пройдет успешно, без исключений, потому что данная ячейка находится на тоЙ жс странице памяти, что и ячейка (100, 100) В подтверждение этого Вы увидите сообщение "No Violation raised" в нижней части диалогового окна
В своих проектах я довольно часто пользуюсь виртуальной памятью и SEH. Как то раз я решил создать шаблонный С++-класс CVMArray, который инкапсулирует все, что нужно для использования этих механизмов Его исходный код содержится в фай ле VMArrayh (он является частью программы-примера Spreadsheet) Вы можете рабо тать с классом CVMArray двумя способами Во-первых, просто создать экземпляр это го класса, передав конструктору максимальное число элементов массива Класс авто матически устанавливает действующий на уровне всего процесса фильтр необрабо танных исключений, чтобы любое обращение из любого потока к адресу в виртуаль ном массиве памяти заставляло фильтр вызывать VirtualAlloc (для передачи физичес кой памяти новому элементу) и возвращать EXCEPTION_CONTINUE_EXFCUTION Ta кое применение класса CVMArray позволяет работать с разреженной памятью (sparse storage), не забивая SEH-фреймами исходный код программы Единственный недоста
ток в том, что Ваше приложение не сможет возобновить корректную работу, если по каким то причинам передать память не удается
Второй способ использования CVMArray — создание производного С++-класса Производный класс даст Вам все преимущества базового класса, и, кроме того, Вы сможете расширить его функциональность — например, заменив исходную виртуаль ную функцию OnAccessViolation собственной реализацией, более аккуратно обрабаты вающей нехватку памяти Программа Spreadsheet как раз и демонстрирует этот спо соб использования класса CVMArray.
Spreadsheet