LINUX.ORG.RU

Правильное использование исключений

 ,


1

3

Я в учебных целях и из спортивного интереса разрабатываю класс для работы с bmp картинками. Функционал пока что примитивный - чтение из файла, запись в файл, вывод на в консоль (да, я упоролся), в дальнейшем будет еще что нибудь, например рисование примитивов на открытом изображении. О всяческих ошибках по моей задумке класс должен сообщать использующей его программе с помощью исключений. Например, если перед вызовом функции read() имя открываемого файла указано не было, выбрасывается исключение, или при чтении файл внезапно кончился, хотя должен был продолжаться, опять выбрасывается исключение.

Является ли частое использование хорошим тоном? Или может быть лучше вообще не использовать исключения, а просто сделать bool read(), который вернет false если случилась ошибка, и другие функции переписать в таком же духе? Какие еще особенности бывают при работе с исключениями?

★★★★

Ответ на: комментарий от post-factum

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

Вы сами себе противоречите, ибо сначала пишете про лапшу и-за мешанины разных способов вернуть ошибку, а потом обвиняете, почему-то именно исключения. На самом деле лапшу пораждают как раз костыли в виде возвращения ошибок через `int'ы, как вы говорите, исключения же обрабатываются всегда единообразно и просто. При этом нормальные C++ библиотеки используют исключения, но если таки используется возврат значений, то самое адекватное что можно с ним сделать - сразу сгенерировать исключение.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

У вас ни на что кроме «вывести куда угодно» фантазии не хватает, в то время как в реальном приложении может понадобиться совершенно произвольная логика.

Так я же не спорю. Я наоборот сказал, что в случае сложной логики функции типа GetFileName() и иже с ними могут пригодиться. Но в вашем примере эти функции просто выводят сообщение в стандартный вывод ошибок, с чем вполне справится и what().

Нет такого стандарта по которому нужно ограничиваться what().

Есть стандартная функция what(), о которой знают все. А других стандартных функций не существует.

У вас просто весьма ограниченное понимание исключений.

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

PS: по-моему, наш спор зациклился. Так что предлагаю брейк. Я не оспариваю необходимости в отдельных случаях использовать дополнительные функции и данные в исключениях, я просто против того, чтобы ими заменяли то, что уже есть, т. е. банально дублировали код. И против этого вы, я надеюсь, ничего не имеете.

aureliano15 ★★
()
Ответ на: комментарий от aureliano15

Так я же не спорю. Я наоборот сказал, что в случае сложной логики функции типа GetFileName() и иже с ними могут пригодиться. Но в вашем примере эти функции просто выводят сообщение в стандартный вывод ошибок, с чем вполне справится и what().

В моём примере GetFileName() испольузется после вывода сообщения, я думал что это очевидно.

Есть стандартная функция what(), о которой знают все. А других стандартных функций не существует.

Нет. Я просто против изобретения велосипедов, если они уже изобретены до нас.

Я же говорю, не понимаете. Исключения разработаны так, чтобы их можно было расширять произвольными данными. what(), повторюсь - не более чем fallback-заглушка. Можно ли обойтись только ей? Можно. Но это ни разу не предпочтительный способ использования исключений.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от slovazap

Это не я противоречу, это девелоперы. Я бы с радостью пользовался унифицированной обработкой ошибок, и мне по большому счёту всё равно какой.

post-factum ★★★★★
()

Правильное использование исключений это когда они из конструкторов выбрасываются. Всё остальное - ересь и не нужно.

try {
 File f("~/Video/pron4ik/devki_v_dushe.mp4");
 VideoPlayer v();
 v.showFullScreen(f);
} catch (std::exception &e) {
 printf("opa4ki! priechali! spasibo sami znaete komy za eto, %s\n" e.code());
}

anonymous
()
Ответ на: комментарий от aureliano15

А исключения считать фатальными ошибками, которые без помощи пользователя исправить нельзя (или вообще нельзя исправить)

Вот именно. Но что считать фатальными ошибками? Это только в хеловордах удобно ловить всё кучей в main, а реальные программы должны быть максимально дуракоустойчивы и реагировать на ошибки по месту их возникновения. Я конечно понимаю как велик соблазн при ошибке забить на всё, кинуть исключение и сообщить пользователю «ПНХ, у тебя комп не работает, попробуй ещё раз», но лучше всё таки сделать что-то более осмысленное и продолжить работу.

Если вслед за чтением сразу идёт обработка этих данных, то мы получим обработанные случайные числа и выведем на экран вместо картинки абракадабру

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

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Хочется узнать, где держат таких идиотов.

eao197 ★★★★★
()
Ответ на: комментарий от no-such-file

Но что считать фатальными ошибками? Это только в хеловордах удобно ловить всё кучей в main, а в реальные программы должны быть максимально дуракоустойчивы и реагировать на ошибки по месту их возникновения.

Это уже зависит от программы. Если говорить о задаче типа той, что описана у тс (работа с bmp-картинками), то, наверно, фатальными ошибками можно считать невозможность открыть файл для чтения, несоответствие содержимого bmp-формату, невозможность открыть устройство графического вывода (окно, графическая консоль или просто указанный файл для записи). В этой задаче вообще всё, по-моему, однозначно, или ошибка, и ничего тут уже не сделаешь, или всё Ok. Разве что можно предусмотреть несколько повторов read() в случае чтения с поцарапанного сидюка. В других задачах будут другие ошибки. Разумеется, доводить до абсурда не надо. Я в первом же своём ответе в этом топике сказал:

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

aureliano15 ★★
()
Ответ на: комментарий от no-such-file

Сударь, какого рода софт вы пишете на C++?

Что ты хочешь узнать этим вопросом? Рекомендую выучить русский язык, и попробовать спросить ещё раз.

демагог детектед

emulek
()
Ответ на: комментарий от aureliano15

не думаю, что тут больше пятерых это понимают…

emulek
()
Ответ на: комментарий от post-factum

Да, писать только ассемблерными вставками.

боянисто, но you make my day. Спасибо.

emulek
()

используй в своих проектах следующий паттерн

int do_smth_with_bmp() 
{
assert(/*то что должно быть истинно ВСЕГДА, например положительные размеры картинки*/);
void* some_raw_local_resource_pointer = nullptr;
int err = OK; // код возврата, содержащий:
              // тип ошибки(fail, warn, succ), 
              // подсистему возникновения ошибки (например конкретная либа) 
              // код ошибки (специфичная ошибка для формата BMP)
for(;;) {
  err = some_stuff0(...);
  if(FAILED(err))
    break;
  // ... countless calls of stuffn(...)
  
  break; // out from for(;;)
}

if (some_raw_resource_pointer)
  free_it_finally(some_raw_local_resource_pointer);

return err;
}

А про исключения забудь. И отладка станет прощее, и жизнь веселее. Если заморачиваешься с количеством строчек - оберни

  if(FAILED(err))
    break;
В макрос, типа BREAK_ON_{FAILURE|WARN} и прибудет с тобой сила.

nikitos ★★★
()
Ответ на: комментарий от aureliano15

и ничего тут уже не сделаешь

А почему это должен решать ТС, а не тот кто будет использовать его поделие? Пример: читаем все файлы bmp в директории, если не файл не читается - пропускаем или используем дефолтную картинку или... да мало ли что можно сделать - зависит от задачи. Если же read бросает исключение, то мне нужно: 1.не забыть про это, 2.обмазать код кучей try/catch (после каждого read).

исключения надо всегда применять действительно в исключительных (т. е. не очень частых) ситуациях

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

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Исключения ограничивают возможности использования кода заставляя действовать определённым образом, т.е. обязательно обрабатывать (все) ошибки явным образом. Это не всегда нужно.

Ну, если обработка ошибки не нужна, то не спорю. Я говорю о ситуациях, когда она нужна.

aureliano15 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.