Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Ieroglif
19 / 19 / 1
Регистрация: 23.06.2011
Сообщений: 238
#1

Когда и где следует использовать механизм исключительных ситуаций? - C++

31.07.2014, 20:25. Просмотров 693. Ответов 11
Метки нет (Все метки)

Вечер добрый, товарищи.
Вопрос у меня в общем-то теоретический и, наверное, размытый, общий.

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

К Страуструпу посылать не надо – читал.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.07.2014, 20:25
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Когда и где следует использовать механизм исключительных ситуаций? (C++):

Когда и где следует использовать механизм исключительных ситуаций? - C++
Раньше при написании Си подобных программ всегда возвращал из функции число или булеву переменную, чтобы понять статус происходящего (...

Обработка исключительных ситуаций. - C++
Пожалуйста,помогите решить..В субботу экзамен,а я физически не успеваю написать 6 программок..( Написать функцию вычисления...

Обработка исключительных ситуаций - C++
Доброго времени суток уважаемы программисты и начинающие программисты :) Скажите, почему появляется ошибка на 6й строке? Задача стоит...

Обработка исключительных ситуаций - C++
Нужна одна работающая программа из 2. 1) Наберите текст программы приведенного примера обработки исключительных ситуаций и...

Обработка исключительных ситуаций! - C++
Составьте программу на языке С++. Обрабатывающую исключительную ситуацию, которая может возникнуть в ходе выполнения программы. ...

Обработка исключительных ситуаций - C++
Всем доброго времени суток, не понимаю как сделать обработку исключительной ситуации когда при вводе количества строк, вводится не целое, а...

11
0x10
2526 / 1706 / 257
Регистрация: 24.11.2012
Сообщений: 4,269
31.07.2014, 20:36 #2
Цитата Сообщение от Ieroglif Посмотреть сообщение
размытый, общий
Ответ будет примерно таким же, ибо вопрос обработки ошибок сам по себе не из простых.
Цитата Сообщение от Ieroglif Посмотреть сообщение
Когда и где этот механизм использовать НЕ стоит?
Тут еще можно более-менее конкретно сказать.
1. В конструкторах - с осторожностью. Следить за тем, чтобы генерация исключения не вела к утечкам памяти.
2. В деструкторах никогда.
3. Плохой идеей будет строить на исключениях логику передачи управления при нормальном ходе выполнения программы (а-ля goto).
Цитата Сообщение от Ieroglif Посмотреть сообщение
Когда и где следует использовать механизм исключительных ситуаций?
Вспоминаем, что исключения - инструмент обработки ошибок. Следовательно, используем для информирования вызывающего кода о произошедших ошибках. Особенно удобно, когда вместе возникновения ошибки недостаточно информации для ее корректной обработки.
Цитата Сообщение от Ieroglif Посмотреть сообщение
Как лучше всего их обрабатывать?
Напрямую зависит от самого исключения. Где-то логично завершить работу приложения. Где-то - залогировать ошибку и продолжить работу.
Цитата Сообщение от Ieroglif Посмотреть сообщение
К Страуструпу посылать не надо – читал.
Но все, что сказал выше, у Страуструпа описано. Что еще добавить?
0
Toshkarik
1148 / 865 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
31.07.2014, 20:55 #3
Цитата Сообщение от 0x10 Посмотреть сообщение
Вспоминаем, что исключения - инструмент обработки ошибок.
Исключения - инструмент обработки исключительных ситуаций. А исключительные ситуации не всегда являются ошибками.
0
Ieroglif
19 / 19 / 1
Регистрация: 23.06.2011
Сообщений: 238
31.07.2014, 21:02  [ТС] #4
Не могли бы привести реальные или приближенные к реальным примеры? Желательно, разномастные.
0
0x10
2526 / 1706 / 257
Регистрация: 24.11.2012
Сообщений: 4,269
31.07.2014, 21:25 #5
Цитата Сообщение от Ieroglif Посмотреть сообщение
Не могли бы привести реальные или приближенные к реальным примеры?
1. Попытка создать вектор отрицательного размера (в общем случае - невозможность захвата ресурса).
2. Подача на вход парсеру невалидной строки.
3. Выход за границы массива.
4. Невозможность продолжения выполнения программы из-за невыполнения одного из этапов алгоритма.
0
Voivoid
675 / 278 / 12
Регистрация: 31.03.2013
Сообщений: 1,339
31.07.2014, 22:51 #6
Цитата Сообщение от 0x10 Посмотреть сообщение
2. Подача на вход парсеру невалидной строки.
По поводу этого пункта я бы уточнил. Бросать исключение стоит только в случае, если данные на вход передаются из надежного источника от которого мы не ожидаем невалидных данных. А вот в случае если мы ожидаем данные от ненадежного источника ( например пользовательский ввод ), то имеет смысл возвращать код ошибки, потому что вероятно все равно придется сразу же проверять что там удалось напарсилось, а писать конструкции вида:

try {
parse();
}
catch ...

это не очень. Ну или по крайней мере имеет смысл делать две функции, одна бросает исключения, а другая возвращает код ошибки
0
Jupiter
Каратель
Эксперт С++
6566 / 3987 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
31.07.2014, 23:01 #7
Цитата Сообщение от Toshkarik Посмотреть сообщение
Исключения - инструмент обработки исключительных ситуаций.
Исключения - инструмент информирования об ошибке/исключительной ситуаций. Обрабатывать или нет решает программист.
0
Tulosba
:)
Эксперт С++
4619 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
31.07.2014, 23:04 #8
Цитата Сообщение от Voivoid Посмотреть сообщение
одна бросает исключения, а другая возвращает код ошибки
Это вроде как бустовский подход. Про всю либу не уверен, но в boost::asio активно практикуется.
Цитата Сообщение от Ieroglif Посмотреть сообщение
Когда и где следует использовать механизм исключительных ситуаций?
Там, где можно диагностировать ошибку, но ещё неясно как её следует обработать. Типичная ситуация - разработка библиотечного кода.
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,822
Записей в блоге: 5
01.08.2014, 02:16 #9
Ieroglif, вот довольно смешной код. Я пытался показать ситуацию, когда без генерации и обработки исключения обойтись трудновато, хотя может и заблуждаюсь.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <new>
using namespace std;
//в конструкторе последовательно выделяются два ресурса:
//это участки памяти под два массива
//моделируем ситуацию когда первый захвачен, а на втором - сбой
//аварийное окончание работы конструктора означает, что его деструктор вызван не будет
//будут только вызваны деструкторы стековых переменных (тут нет стековых переменных - классов))
//это значит что поймав такое исключение нужно проанализировать и если нужно освободить выделенную память самостоятельно 
struct SomeThingWillHappen{
int arr_size;
int *arr1;
int *arr2;
 
SomeThingWillHappen( int n){
int err_code=0;
arr_size = n;
 
//следующий блок try - catch не должен сработать, он написан подобно второму
try{
err_code  = 1;
arr1 = new int[arr_size];
err_code  = 0;
}
catch(bad_alloc& ba){
cerr << "bad_alloc caught: " << ba.what() << '\n';
//это первый ресурс и если не выделилась память, то и освобождать нечего
//передаём инфу наружу и всё
throw err_code ;//прерывание конструктора и передача исключения
}
//а этот мы запустим сами
try{
err_code = 2;
throw err_code;//имитация сбоя выделения памяти под массив arr2 
arr2 = new int[arr_size];//это не выполнится
err_code  = 0;
}
catch(int p){
cerr  <<"Bad_alloc arr2 at ctor SomeThingWillHappen( int n) "<< p << endl;
if(err_code == 2) {
//а тут понятно, что всё рухнуло и память под первый массив без нас никто не освободит
cerr <<"The memmory for arr1 succefuly allocated and will be released "<< p << endl;
//тип int - встроенный и запускать деструкторы по массиву не нужно, просто освобождаем
delete []arr1;
cerr <<"The memmory for arr1 released "<< endl;
err_code = 2;
throw err_code ;
}
system("pause");
}
for( int i = 0; i < arr_size; ++i) {
    arr1[i]=0;
    arr2[i]=i;
}
}
~SomeThingWillHappen(){
delete []arr1;
delete []arr2;
cout<<"destructor "<< endl;
system("pause");
}
};
int main()
{
    try{
SomeThingWillHappen a(4);
    }
    catch(int err_code){
        if(err_code == 1){
                  cerr <<"Bad_alloc arr1 at ctor SomeThingWillHappen( int n) " << endl;
//--------------------------------------------
////treat1
//--------------------------------------------
    }
        if(err_code == 2){
            cerr <<"Bad_alloc arr2 at ctor SomeThingWillHappen( int n) " << endl;
cerr <<"show/program)) must go on and we will treat the situation";
//--------------------------------------------
//treat2
//--------------------------------------------      
        }
    }
cin.get();
return 0 ;
}
0
Voivoid
675 / 278 / 12
Регистрация: 31.03.2013
Сообщений: 1,339
01.08.2014, 03:04 #10
Цитата Сообщение от IGPIGP Посмотреть сообщение
вот довольно смешной код
Когда и где следует использовать механизм исключительных ситуаций?

Цитата Сообщение от Tulosba Посмотреть сообщение
Это вроде как бустовский подход
Ну, это по-моему здравомысленный подход
1
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,822
Записей в блоге: 5
01.08.2014, 03:23 #11
Цитата Сообщение от Voivoid Посмотреть сообщение
вот довольно смешной код

Еще один "умный" весчь скажу. Я не имею существенного опыта и пока, RAII напоминает мне инструкцию/манифест под лозунгом: сделай сам.
0
Evg
Эксперт CАвтор FAQ
18692 / 6658 / 469
Регистрация: 30.03.2009
Сообщений: 18,639
Записей в блоге: 29
02.08.2014, 13:35 #12
На пальцах можно сказать, что в любом культурном компиляторе поддержка исключений устроена так, что оператор try работает очень быстро, а оператор throw/catch работает очень медленно. Ещё одной особенностью исключения является многоуровневый выход из процедур.

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

Возьмём некоторый абстрактный алгоритм, который устроен в виде цепочки вызовов. При этом может получиться, что входные данные для алгоритма заданы некорректно, но это выясняется глубоко (т.е. через несколько вызовов). А поэтому если делать реализацию без исключительных ситуаций, то получится так, что, допустим, ошибка может обнаружиться на 10-м уровне вложенности, а потому чтобы вернуть в точку начала информацию об ошибке требуется все промежуточные 9 уровней вложенности писать так, чтобы они тоже следили за этой ошибкой

Типа того:

C++
int main (void)
{
  /* Вызываем наш алгоритм. Если в ответ вернули true, значит всё хорошо,
   * если вернули false, значит были ошибки во входных данных */
  res = func (...);
  if (res == false)
    /* выдаём информацию об ошибке */
}
 
bool func (...)
{
  ...
  res = func1 (...);
  if (res == false)
    /* Где-то на нижних уровнях случилась ошибка, возвращаем
     * информацию об этом наверх */
    return false;
  ...
  return true;
}
 
/* Здесь по смыслу всё то же самое */
bool func1 (...)
{
  ...
  res = func2 (...);
  if (res == false)
    /* Где-то на нижних уровнях случилась ошибка, возвращаем
     * информацию об этом наверх */
    return false;
  ...
  return true;
}
 
/* Далее по такому принципу ещё несколько уровней */
 
bool func10 (int x, int y)
{
  ...
  /* И вот уже на самом низком уровне мы можем проверить,
   * что какие-то промежуточно вычисленные параметры оказываются
   * некорректными */
  if ((a + b) > 10 && (a * b) < 7 && ....)
    return false;
  ...
  return true;
}
При таком подходе мы должны постоянно отслеживать на всех уровнях возможные ошибки, произошедшие на более низких уровнях. И весь этот геморрой только ради того, чтобы в конечном итоге наверху выдать сообщение о том, что входные данные были некорректными. А может потребоваться ещё и детализация ошибки - т.е. не просто "данные корректны" или "данные некорректны", а ещё и с описанием того, что конкретно некорректно и на каком уровне проявилось, то код будет сильно перегружен обработкой ситуаций, которые, грубо говоря, являются нерабочими - т.е. информация об ошибках в боевом режиме программы будет выдаваться редко, но время на постоянную проверку на всех уровнях будет тратиться.

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

C++
int main (void)
{
  /* Вызываем наш алгоритм. Если было брошено исключение, значит
   * были ошибки во входных данных */
  try
  {
    func (...);
  } catch (...)
  {
    /* выдаём информацию об ошибке */
  }
}
 
/* Обращаем внимание на то, что нам уже не нужно возвращать
 * информацию о корректности или неорректности */
void func (...)
{
  ...
  func1 (...);
  ...
}
 
/* Здесь по смыслу всё то же самое */
void func1 (...)
{
  ...
  func2 (...);
  ...
}
 
/* Далее по такому принципу ещё несколько уровней */
 
void func10 (int x, int y)
{
  ...
  /* И вот уже на самом низком уровне мы можем проверить,
   * что какие-то промежуточно вычисленные параметры оказываются
   * некорректными. И только здесь мы генерируем исключительную
   * ситуацию, про которую более высокие уровни даже не знают,
   * а потому и не тратят время на её обработку */
  if ((a + b) > 10 && (a * b) < 7 && ....)
    trow ...;
  ...
}
4
02.08.2014, 13:35
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.08.2014, 13:35
Привет! Вот еще темы с ответами:

Обработка исключительных ситуаций - C++
Код программы,Что та не робит помогите #include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include&lt;conio.h&gt; using namespace std; int...

Обработка исключительных ситуаций - C++
Здравствуйте, друзья. Подскажите, пожалуйста, как можно при помощи try-throw-catch &quot;защититься&quot; от ввода пользователем &quot;не того типа...

Обработка исключительных ситуаций - C++
Мне нужно было создать шаблонный класс и написать обработку исключающих ситуаций. Вот, что я сделал #pragma once #include &lt;iostream&gt;...

Обработка исключительных ситуаций - C++
Правильно ли тут я обрабатываю исключения? #pragma once #include &lt;iostream&gt; #include &quot;stdio.h&quot; #include &quot;stdlib.h&quot; #include...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru