Лекция 16 (лекции (2002)), страница 2

2019-09-19СтудИзба

Описание файла

Файл "Лекция 16" внутри архива находится в папке "лекции (2002)". Документ из архива "лекции (2002)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "Лекция 16"

Текст 2 страницы из документа "Лекция 16"

}

catch(Err1 e)

{…}

catch(Err2 e)

{…}

catch(…){…}

Если в конструкции S возникло исключение, оно имеет какой-то тип данных, и мы пытаемся отождествить этот тип данных с Err1, если не проходит – с Err2 и т.д. В данном случае последняя ловушка отождествляется с любым типом данных.

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

catch(тип){…}

Такие случаи встречаются редко, поскольку чаще всего нам нужна эта информация.

В MFC в классе CException есть метод, который называется ReportError( ). Простейший способ исправить ошибку – отрапортовать о ней и считать, что ничего не случилось.

Как и в Аде, если блок обработки исключений проработал нормально, исключение считается обработанным, а блок – исправившим ошибку.

Как и в Аде в С++ есть укороченная форма оператора возбуждения исключения

throw;

У него нет параметров, поскольку, как и в Аде, он может встречаться только внутри блоков обработчиков. Естественно, что речь идет об исключении, которое при этом обрабатывается.

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

catch(Err e)

{throw e;

throw;}

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

В компиляторе Visual C++ вначале была реализована некоторая упрощенная схема обработки исключений, которые назывались structured. Стандартный механизм был слишком тяжелым, чтобы реализовать его сразу. Каждая ошибочная ситуация с точки зрения ОС (например, деление на 0, выход за границу памяти – access valuation, разыменование нулевого указателя и т.д.) имеет свой системный код. Этот системный код и был исключением в первом "структурном" механизме обработки исключений в С++. Естественно, этот механизм остался и сейчас. Часто бывает, что нам необходимо эти исключения от ОС завернуть в исключения от языка С++. Именно для этого иногда применяется возбуждение новых исключений.

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

Поскольку в С++ есть наследование, необходимо сказать несколько слов о механизме отождествления. Дело в том, что при наследовании возникает иерархия типов. Считается, что если есть тип Т1, и из него выведено прямо или косвенно несколько других типов Ti, то всякий объект типа Тi одновременно является объектом типа Т1. Если при такой иерархии написать

catch(T1 e){…}

catch(Ti e){…}

хороший компилятор в этом месте должен выдать предупреждение. При возникновении исключений по правилам обработчики перебираются сверху вниз. Если возникло исключение Т1, отождествление произойдет в первом случае, и проработает соответствующий блок. Если произошло исключение типа Ti, то, т.к. объект Ti является одновременно объектом Т1, отождествление опять произойдет в первом случае. Система обработки исключений не устраивает хитрый поиск: если не подошел ни один тип точно, не подойдет ли теперь какой-нибудь не точно. Если можно хоть как-то выполнить отождествление Ti с Т1, оно выполняется. Если есть такая иерархия, то любые типы, которые выведены из Т1 будут перехватываться в этом месте.

Реально мы используем исключения, которые пишем не сами. Как правило, мы пользуемся какими-то библиотеками (иначе это напоминает научно-исследовательское или игровое программирование). В этих библиотеках есть какие-то библиотечные классы исключений. Как правило, программист использует исключения, выведенные из этих классов. (В MFC это класс CExeption.) Следовательно, так или иначе, у нас все исключения являются родственниками прямыми (по одной прямой) или двоюродными. Если родственники двоюродные это не страшно. Если родственники прямые, то чем моложе родственник в иерархии, тем раньше надо ставить обработчик. Это общее правило. В нашем примере есть ошибка, и мы можем опустить второй обработчик. Правильно будет написать

catch(Ti e){…}

catch(T1 e){…}

Конструкция

catch(…){…}

плоха тем, что мы не имеем никакой информации об обрабатываемом исключении. Если у всех исключений есть единый предок, то это можно исправить. Например, при использовании MFC если мы в конце напишем

catch(CException e){…}

это означает, что если везде в программе мы используем только исключения, выведенные из типа CExeption (а все классы MFC возбуждают только исключения выведенные из класса CExeption), то с семантической точки зрения это то же самое, что

catch(…){…}

но нам доступна информация об исключении.

Возможен случай, что обработчика не нашлось. Сначала у нас работает main,

main

try{…}…

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

terminate( );

Система обработки исключений в случае, если не найден ни один обработчик для данного исключения, вместо того чтобы делать системный вызов abort, который просто выбрасывает программу, вызывается функция terminate. Мы сами можем ее вызывать. Она вызывает внутри себя некоторый обработчик, который может устанавливать пользователь. Как правило, мы terminate не вызываем, за нас это делает система обработки исключений. Мы можем вызвать функцию

set_terminate(f);

у которой в качестве аргумента будет новый обработчик. Возвращает эта функция старый обработчик.

typedef void (* pvf) (void);

set_terminate в качестве параметра получает pvf и возвращает pvf, с тем чтобы мы могли установить свою реакцию, потом вернуть старую и т.д. Ничего особенно выдающегося функция terminate сделать не может. Максимум, что она может – выдать какое-то осмысленное сообщение об ошибке и попытаться перезапустить процесс.

Общий синтаксис функций в С++, как и в С

тип_возвращаемого_значения имя(аргументы) блок

Блок представляет из себя тело функции. В С++ этот синтаксис несколько расширен.

тип_возвращаемого значения имя(аргументы) [список_исключений] блок

Список_исключений в болшинстве функций отсутствует. Список_исключений – это ключевое слово throw, за которым в скобках идет список типов. Например:

void f( ) throw(X, Y) {блок}

Эта запись означает, что в блоке могут возникать необработанные исключения только типа X и Y. Если в блоке f возникнет необработанная исключительная ситуация, которая не отождествляется ни с X, ни с Y, то поскольку программист этого не ожидал, он, естественно, ничего не предпримет, чтобы обрабатывать исключительные ситуации, отличные от этих. Поэтому имеет смысл не продолжать распространение этого исключения, а сбросить программу. При этом вызывается не функция terminate, а функция

unexpected( );

Она, как и terminate, вызывается системой обработки исключений. Есть функция

set_unexpected(f);

которая позволяет поставить свой обработчик unexpected. Как и terminate, unexpected мало что может сделать – более или менее осмысленную диагностику и возможный перезапуск процесса.

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

В общем, механизм обработки исключений схож с механизмом обработки исключений в Аде.

Delphi, C#, Java.

Эти языки похожи между собой.

  1. Определение.

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

В Delphi этот класс называется TException.

В C# - Exception.

В Java - Throwable

По минимуму, в исключительном классе есть некоторый текст и методы, которые позволяют его выдать, и какая-то дополнительная информация.

В Java, если исключение не будет обработано, то, по крайней мере, в отличии от С++, будет выдан весь стек от места, где произошла ошибка, до метода main в главном классе, в какой строке произошла ошибка, за счет того, что в байт-коде языка Java очень полная информация о среде выполнения, в отличие от обычного бинарного кода, который генерирует компилятор языка С++.

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

  1. Возникновение.

В Delphi есть оператор

raise exp;

в C# и Java -

throw exp;

exp – некоторое выражение типа, который относится к базовому типу, или является производным от него.

  1. Распространение.

В этих языках нет механизма свертки стека. Это понятие специально выделяется в языке С++ потому, что в С++ есть семантика автоматического вызова деструктора. Во всех этих трех языках семантики автоматического вызова деструктора нет. В Java вообще нет понятия деструктора.

MIL – Microsoft Intermediate Language – Промежуточный Язык Microsoft. Microsoft всячески призывает изучать промежуточный язык. Если вы изучите MIL, то вам станет ясно, что деструктор языка C# сводится к тому, что компилятор подставляет вызов метода finalize, а во всех руководствах к C# стыдливо говориться, что деструктор, в этом языке только называется деструктором, но на самом деле им не является.

Т.е. реально ни в C#, ни в Java деструкторов нет. В Delphi деструктор есть, но автоматической семантики вызова этого деструктора нет. Вот почему в этих языках нет понятия свертки стека. Т.е. свертка ближе к языку Ада, но она существенно легче реализуется.

С++ очень удобная семантика работы с ресурсами (захват ресурса в локальном объекте через конструктор, освобождение – через деструктор). В этих языках – по-другому. Во всех этих трех языках присутствует конструкция, которая отсутствует в языке С++:

в C# и Java

try{

блок

} finally {…}

После finally стоит не обработчик исключительных ситуаций, а код, который выполняется всегда вне зависимости от того, каким образом завершился блок – нормально или аварийно. Блок, стоящий после catch(…), будет выполняться, только если возникло исключение.

Синтаксис Delphi практически такойже

try

операторы

finally

end;

Операторы, стоящие после finally, выполняются всегда, не зависимо от того, было возбуждено исключение или нет. Этот оператор появился потому, что он моделирует семантику свертки стека. Работа с ресурсами в этих языках

захват ресурса

try

операторы

finally

освобождение ресурса

end;

Если ресурс – динамическая память, то в языках C# и Java писать его освобождение не нужно – она освободится. Но динамическая память – не единственный ресурс. Внешние устройства: принтеры, COM-порты и многое другое - внешние ресурсы, которые не освобождаются автоматически. Их необходимо освобождать вручную. Поэтому во всех трех языках присутствует такая конструкция. При захвате ресурса надо писать блок try – finally потому, что в процессе распространения исключений никаких сверток стека нет.

Тем не менее, принцип распространения исключений во всех этих языках одинаков, а именно – принцип завершения.

  1. Обработка исключений.

Синтаксис Java, C# очень схож с синтаксисом С++:

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5288
Авторов
на СтудИзбе
417
Средний доход
с одного платного файла
Обучение Подробнее