cpp-oop (823968), страница 20
Текст из файла (страница 20)
По умолчанию эта функциявызывает функцию abort(), которая аварийно завершает текущий процесс.Автоматическисоздаваемуюфункциюterminate()можнозаменитьсобственной. Для этого используют функцию set_terminate():void my_terminate(){<Собственная обработка завершения>}…set_terminate(my_terminate);Функция set_terminate()возвращает адрес предыдущей программы обработкизавершения, что позволяет при необходимости вернуть ей управление.ОглавлениеИванова Г.С., Ничушкина Т.Н. «Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»1517.2Механизм исключений СВ языке С используется так называемое структурное управление исключениями.Именно данный способ обработки исключений используется при необходимостиперехватить исключения от операционной системы Win32.В основе структурного управления исключениями лежат конструкции__try…__exceptи__try…__finally.Перваяобеспечиваетобычнуюобработку исключения, вторая – завершающую.Обычная обработка программируется следующим образом:__try {<Защищенный код>}__except(<Фильтрующее выражение>){<Обработка исключений>}Фильтрующее выражение может принимать следующие значения:• EXCEPTION_EXECUTE_HANDLER – управление должно быть передано наследующий за ним обработчик исключения.
В этом случае по умолчанию при обратномпросмотре стека вызовов активизируются деструкторы всех локальных объектов,созданных между местом генерации исключения и найденным обработчиком;• EXCEPTION_CONTINUE_SEARCH – производится поиск другого обработчика;• EXCEPTION_CONTINUE_EXECUTION – управление возвращается в то место, гдебыло обнаружено исключение без обработки исключения (отмена исключения).Как правило, в качестве фильтрующего выражения используется функция, котораявозвращает одно из трех указанных выше значений.Библиотека excpt.h включает также функции, позволяющие получить некоторуюинформацию об исключении:GetExceptionCode() – возвращает код исключения.GetExceptionInformation()–возвращаетуказательнаструктуру,содержащую описание исключения.ОглавлениеИванова Г.С., Ничушкина Т.Н.
«Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»152Существует ограничение на вызов этих функций: они могут вызываться тольконепосредственно из блока __except(), например:#include <excpt.h>int filter_func(EXCEPTION_POINTERS *);...EXCEPTION_POINTERS *xp = 0;__try {foo();}__except (filter_func(xp = GetExceptionInformation())){/* получение информации об исключении */}или с использованием составного оператора:__except((xp = GetExceptionInformation()),filter_func(xp))Фильтрующая функция не может вызывать функциюGetExceptionInformation(), но результат этой функции можно передать вкачестве параметра.Функция GetExceptionInformation() возвращает указатель на структуруEXCEPTION_POINTERS:struct EXCEPTION_POINTERS{EXCEPTION_RECORD *ExceptionRecord;CONTEXT *Context;};Структура EXCEPTION_RECORD в свою очередь определяется следующим образом:struct EXCEPTION_RECORD{DWORD ExceptionCode;// код завершенияDWORD ExceptionFlags; // флаг возобновленияОглавлениеИванова Г.С., Ничушкина Т.Н.
«Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»153struct EXCEPTION_RECORD *ExceptionRecord;void *ExceptionAddress;// адрес исключенияDWORD NumberParameters; // количество аргументовDWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];// адрес массива параметров};Обычно фильтрующая функция обращается к информации ExceptionRecord,чтобы определить, следует ли обрабатывать исключение данным обработчиком. Ноиногда этой информации обработчику исключения оказывается недостаточно, и тогдаиспользуют поля, собранные в структуру CONTEXT.Например, если исключение не обрабатывается, а управление возвращается обратновточкугенерацииисключения(значениефильтрующеговыраженияравноEXCEPTION_CONTINUE_EXECUTION), то при возврате вновь возникнет то жеисключение.
Изменив соответствующие поля структуры CONTEXT, мы избегаемзамкнутого круга, например:static int xfilter(EXCEPTION_POINTERS *xp){int rc;EXCEPTION_RECORD *xr = xp->ExceptionRecord;CONTEXT *xc = xp->Context;switch (xr->ExceptionCode){case EXCEPTION_BREAKPOINT:++xc->Eip;/* в коде программы остались встроенныеточки останова, перешагнем через них,изменив адрес команды на 1байт */rc = EXCEPTION_CONTINUE_EXECUTION;break;case EXCEPTION_ACCESS_VIOLATION:rc = EXCEPTION_EXECUTE_HANDLER;break;ОглавлениеИванова Г.С., Ничушкина Т.Н.
«Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»154default:// продолжить поиск обработчикаrc = EXCEPTION_CONTINUE_SEARCH;break;};return rc;}...EXCEPTION_POINTERS *xp;__try{func();}__except(xfilter(xp = GetExceptionInformation())){abort();}Для генерации структурного исключения используется специальная функция:void RaiseException(DWORD <Код исключения>,DWORD <Флаг>,DWORD <количество аргументов>,const DWORD *<адрес массива 32-разрядных аргументов>);где <флаг> может принимать значения:0 – исключение возобновимо;EXCEPTION_NONCONTINUABLE – исключение не возобновимо.Пример 7.2. Обработка структурного исключения.#include <string.h>#include <stdlib.h>#include <windows.h>#include <excpt.h>#include <iostream>ОглавлениеИванова Г.С., Ничушкина Т.Н.
«Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»155using namespace std;#define MY_EXCEPTION 0x0000FACEvoid func(){RaiseException(MY_EXCEPTION,0,0,0); // исключение}DWORD ExceptionFilter(DWORD dwCode){if (dwCode==MY_EXCEPTION) // фильтрация исключенияreturn EXCEPTION_EXECUTE_HANDLER;elsereturn EXCEPTION_CONTINUE_SEARCH;}void somefunc(){__try { func(); }__except(ExceptionFilter(GetExceptionCode())){cout<<"MyException"<<endl;}}void main(){somefunc();system("pause");}Структурноеуправлениеисключениямиподдерживаеттакжезавершающуюконструкцию, которая выполняется независимо от того, было ли обнаружено исключениепри выполнении защищенного блока.Пример 7.3. Совместное применение простой и завершающей обработкиисключений.#include <stdio.h>#include <windows.h>ОглавлениеИванова Г.С., Ничушкина Т.Н.
«Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»156void main(){puts("hello");__try{puts("in try");__try{puts("in try");RaiseException(0,0,0,0); // генерация исключения}__finally{puts("in finally");}}__except( puts("in filter"), EXCEPTION_EXECUTE_HANDLER ){puts("in except");}puts("world");system("pause");}Результат работы программы:helloin tryin tryin filterin finallyin exceptworldОглавлениеИванова Г.С., Ничушкина Т.Н. «Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»157Для продолжения нажмите любую клавишу .
. .При выполнении завершающей обработки, так же как и при обычной обработке,вызываются деструкторы созданных локальных объектов. То же самое происходит, еслиисключения остаются необработанными. Локальные объекты не уничтожаются только втом случае, если необработанным остается исключение Win32.ОглавлениеИванова Г.С., Ничушкина Т.Н. «Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»158Совместное использование различных механизмов обработки исключений7.3При программировании обработки исключений операционной системы Win32следует иметь в виду, что:1) исключения Win32 можно обрабатывать только __try…__except или,соответственно, __try…__finally; оператор catch эти исключения игнорирует;2) неперехваченные исключения Win32 не обрабатываются функцией обработкинеперехваченных исключений и функцией terminate(), а передаются операционнойсистеме, что обычно приводит к аварийному завершению приложения.В свою очередь, исключения С++ не видимы для __except.Если возникает необходимость перехвата структурных исключений и исключенийС++ для одной последовательности операторов, то соответствующие конструкциивкладываются одна в другую.Пример 7.4.
Совместная обработка исключений различных типов.Рассмотриморганизацию совместной обработки исключения Win32 «Деление на нуль в вещественнойарифметике» и исключения С++.В файле Exception.h определим класс исключения и функцию, использующуюэто исключение:#ifndef ExceptionH#define ExceptionH// класс Мое исключениеclass MyException{private:// поле сообщенияchar* what;public:MyException(char* s);MyException(const MyException& e);~MyException();char* msg()const;};void func();#endifОглавлениеИванова Г.С., Ничушкина Т.Н. «Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»159Тела методов опишем в файле Exception.cpp:#include <string.h>#include "Exception.h"MyException::MyException(char* s = "Unknown"){ what = strdup(s);}MyException::MyException(const MyException& e ){ what = strdup(e.what); }MyException::~MyException(){ delete[] what; }char* MyException::msg() const{ return what; }Вызов защищенной функции осуществляем в основной программе:#include <stdlib.h>#include <windows.h>#include <iostream>#include "exception.h"using namespace std;void func1(){int *p; // неинициализированный адрес__try{*p = 13;// ошибка!!}__except(EXCEPTION_EXECUTE_HANDLER){// перевод исключения Win32 в исключение С++throw(MyException("Wrong adresing!"));}}ОглавлениеИванова Г.С., Ничушкина Т.Н.
«Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»160void func2(){try{func1();}catch(const MyException& e){cout<<e.msg()<<endl;}}void func(){__try{func2();__finally}{ cout<<"Finally execution"<<endl; }}void main(){func();system("pause");}ОглавлениеИванова Г.С., Ничушкина Т.Н. «Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»161Вопросы для самоконтроля1.
Какие средства обработки ошибок были включены в базовую объектную модельС++? Как их можно использовать?Ответ.2. Почему в С и C++ сосуществуют два различных механизма обработкиисключений? Расскажите о каждом из них. В каких случаях они используются? Возможноли их совместное применение?Ответ.ОглавлениеИванова Г.С., Ничушкина Т.Н. «Объектно-ориентированное программирование на языке C++ в среде Microsoft Visual Studio 2008»162Создание и уничтожение динамических объектов. «Умные8указатели»8.1Проблемы работы с динамическими объектамиСовременное программирование предполагает интенсивную работу с динамическойпамятью.