
- •Объектно-ориентированное программирование
- •Лабораторная работа №1 Работа с проектами в среде Borland c.
- •Лабораторная работа №2
- •Лабораторная работа №3 Переопределение операций.
- •Лабораторная работа №4 Производные классы.
- •Лабораторная работа №5 Ввод-вывод в потоки.
- •Лабораторная работа №6
- •Курсовой проект
- •Литература
- •Объектно-ориентированное
Лабораторная работа №6
Обработка исключительных ситуаций на С++.
Цель работы
Освоить приемы обработки исключений при возникновении математических ошибок и ошибок недостатка памяти, прерываний операционной системы.
Краткие теоретические сведения
Для обработки сигналов программе из операционной системы существует функция signal, которая позволяет процессу выбрать один из нескольких способов управления сигналом прерывания от операционной системы. Для ее использования необходим файл signal.h, а прототип имеет вид:
void (*signal(int sig, void(*func)(int sig [,subcode])))(int sig);
sig: SIGABRT SIGILL SIGSEGV SIGFPE SIGINT SIGTERM
Функция возвращает предыдущее значение func , если она завершилась успешно, или SIG_ERR- если нет. Аргумент должен быть одной из следующих констант, определенных в файле signal.h:
SIGABRT, SIGBREAK, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, SIGUSR1, SIGUSR2, SIGUSR3.
Действие, предпринимаемое при получении сигнала прерывания, зависит от значения func. Аргумент func должен быть либо адресом функции или одной из объявленных констант, описанных ниже и определенных в файле signal.h:
Значение |
Описание |
SIG_IGN |
Игнорирует сигнал прерывания. Это значение не должно быть использовано для SIGFPE, поскольку состояние процесса с плавающей запятой слева не определено. |
SIG_DFL |
Использует ответ, определенный по умолчанию в операционной системе |
Адрес функции |
Устанавливает указанную функцию в качестве управляющей для данного сигнала |
Поскольку функции управления сигналами обычно вызываются асинхронно при возникновении прерываний, им представляется возможность перехватить управление, если операция, вызвавшая прерывание, не завершена и если состояние процесса не определено.
Значительная часть ошибок в программе возникает при выполнении математических операций и вызове математических функций. Для управления такими ошибками служат функции matherr и _matherrl, определение которых содержится в файле math.h - модифицируемые пользователем функции управления математическими ошибками. Прототипы этих функций имеют вид:
int matherr(struct exception *e);
int _matherrl(struct _exceptionl *(e));
Заметим, что matherr вызывается, когда ошибка генерируется математической библиотекой, а _matherrl - когда ошибка генерируется математическими функциями, возвращающими значения типа long double.
Обе эти функции служат пользовательскими обработчиками прерываний, которые вы можете заменять, написав собственные программы - обработчики математических ошибок. Эти функции полезны для перехвата ошибок диапазона, вызванных математическими функциями. Они не перехватывают исключительные ситуации, связанные с плавающей запятой, такие, как деление на 0. Для перехвата таких ошибок используется функция signal. Будучи переопределенными пользователем, они заменяют версии по умолчанию в библиотеке Си. Пользовательские версии этих функций должны возвращать 0, если им не удалось исправить ошибку и ненулевое значение, если ошибка исправлена.
Возвращаемое значение по умолчанию при ошибках underflow или tloss равно 1, в противном случае оно равно 0.
Когда функция matherr (или_matherrl) возвращает 0, (указывая, что она не в состоянии исправить ошибку), она устанавливает errno равным 0 и печатает сообщение об ошибке. Когда функция возвращает не ноль (указывая, что она способна исправить ошибку), errno не устанавливается и сообщение об ошибке не печатается. Обе эти функции могут модифицировать e -> retval, который возвращается в вызывающую программу.
При выделении динамической памяти возможна ситуации с ее нехваткой. Для разрешения подобных ситуаций служит функция set_new_handler, описанная в файле new.h и устанавливающая функцию, которая будет вызываться, когда запрос на выделение памяти с помощью операции new() не может быть успешно выполнен. Ее прототип имеет вид:
void ( * set_new_handler(void (* my_handler)() ))();
По умолчанию операция new() возвращает 0, если она не может выделить память. Вы можете повлиять на ее поведение по умолчанию установкой нового обработчика прерываний и вызова set_new_handler. Если операция new() не может выделить требуемый объем памяти, она вызывает обработчик прерываний, который был установлен предыдущим вызывом set_new_handler. my_handler должен содержать действия, предпринимаемые при невозможности выполнить запрос операции new() на выделение памяти. Если произойдет возврат из my_handler, то new() вновь попытается выполнить запрос на выделение памяти. В идеале my_handler должен освободить память и вернуть управление, так что new() будет способна выполнить запрос на выделение памяти и программа сможет продолжиться. Если же my_handler не может обеспечить требуемый new() объем памяти, my_handler должен закончить работу программы. В противном случае будет создан бесконечный цикл.
Установка обработчика прерываний по умолчанию производится вызовом set_new_handler(0).
Предпочтительно, чтобы Вы перегрузили операцию new() для соответствующей работы Вашего приложения.
Напомним, что set_new_handler возвращает старый обработчик прерываний, если он был определен. По умолчанию обработчик прерываний не установлен. Определенная пользователем функция - аргумент set_new_handler, именуемая здесь my_handler, не должна возвращать значение.
Методические указания
При описании классов введите статический массив указателей на объекты класса.
При написании конструкторов используйте эти указатели для хранения адресов создаваемых объектов.
При написании деструкторов удаляйте адреса уничтожаемых объектов из статического массива.
Перегрузите операции помещения и извлечения для ввода - вывода объектов класса отдельно для работы с консолью и текстовым файлом.
Разработайте отдельную функцию для вывода списка всех объектов класса.
В головной программе предусмотрите явный вызов деструктора перед выводом списка объектов класса.
Порядок выполнения работы
Для заданий, выполненных в предыдущих работах, перегрузить операции ввода - вывода объектов класса, разработать функции, позволяющие осуществлять ввод и вывод отдельного объекта и всего списка объектов класса с/на консоль и в/из текстового файла в удобной форме.
Изменить демонстрационную программу, включив в нее вызов разработанных функций, конструкторов и деструкторов для изменения количества объектов.
Контрольные вопросы
Стандартные потоки в С.
Иерархия потоковых классов.
Операции помещения в поток и извлечения из потока, их использование.
Как проконтролировать состояние потока?
Файловые потоки
Режимы открытия файлов
Функции ввода - вывода и позиционирования в файлах.
Статические члены и методы класса.
Для задач из предыдущей лабораторной работы добавить обработку исключений при возникновении ошибок: недостатка памяти, выход за пределы диапазона допустимых значений и т.д. Обработку исключений реализовать на уровне методов и демонстрационной программы. Изменить демонстрационную программу так, чтобы она демонстрировала механизм исключений.