Название: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 24, 2014, 12:12 10/18/2014 По итогу этой темы написал небольшую статью: Стратегия обработки ошибок пользователя с помощью собственных классов исключений (http://www.prog.org.ru/topic_27797_0.html)
Привет! Расскажите, пожалуйста, о своём опыте, как вы на практике обрабатываете ошибки в ваших приложениях на Qt. Применяете исключения или нет? Чем чревато применение исключений в приложениях на Qt? В применении исключений больше пользы или вреда? Улучшают ли исключения архитектуру программного проекта? У меня есть пример. В этом примере открывается текстовый файл, из него читаются данные и данные записываются в другой текстовый файл. Как я понимаю, есть несколько способов возвращать ошибку и значение из функции: 1) Функция возвращает 0 при отсутствии ошибок и -1 в случае ошибки. Посмотреть код ошибки можно с помощью глобальной переменной errno (глобальной для потока). Значение функции возвращаем через ссылку-параметр функции. 2) Функция возвращает 0 в случае ошибки, так как 0 в C и C++ - это false. Функцию, тогда можно вызывать так: if ( func( ) ). Посмотреть код ошибки можно с помощью глобальной переменной errno. Значение функции возвращаем через ссылку-параметр функции. 3) Функция возвращает, как значение, так и код ошибки через структуру, либо класс, либо std::pair, либо std::tuple 4) Слышал, есть ещё способ с nullptr. Но так пример и не нашёл. 5) Ещё я слышал есть механизм setjmp()/longjmp(). Но его в C++ нельзя использовать, там какая-то замута с конструкторами, деструкторами и стеком. Да и в C его не используют (или не рекомендуют) 6) Функция возвращает 0 при отсутствии ошибок и код ошибки (errno не используется). Значение функции возвращаем через ссылку-параметр функции (можно сделать наоборот, что функция будет возвращать значение, а код ошибки через ссылку-параметр). Пример без исключений: Код
Пример с исключениями Код
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 24, 2014, 13:10 Есть ещё подход аля winapi.
Выполняем функцию, запрашивает GetLastError(). Если 0 - значит всё хорошо. Если другое - ппц всё пропало. Т.е. 1 глобальная функция, возвращающая состояние последней выполненной функции. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 24, 2014, 15:36 Спасибо! Я забыл про этот подход написать. Пользовался им когда-то. Здесь можно ошибки смотреть:
- http://msdn.microsoft.com/en-us/library/cc231199.aspx - http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx но этот подход системно зависимый, в отличае от глобальной переменной errno. Так что же по поводу вопросов в начале темы? Исключения в приложениях на Qt это благо? Или лучше их избегать? Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 24, 2014, 15:58 Это С++. Тут можно что угодно во благо, если умеешь. Но Qt не использует исключения, по слухам это позиция разработчиков.
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 24, 2014, 16:26 Спасибо! Этот ответ мне нравится :) Значит не зря я копаю в сторону исключений :)
Лучше всего об исключениях написано в этой книге (много примеров): Название: Professional C++ Год: 2011 Автор: Marc Gregoire, Nicholas A. Solter, Scott J. Kleper Количество страниц: 1104 Язык: английский Скачать: http://kickass.to/wrox-professional-c-plus-plus-2nd-edition-2011-retail-ebook-debt-t7461950.html Исходники: http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449,descCd-DOWNLOAD.html Я применил их подход к своей программке с чтением и записью в файл. Здесь создаются свои классы исключений, что позволяет, к примеру, указать строку, с некорректными данными: Error reading input.txt at line 2. Применяются наследование и полиморфизм. Правда в консоль (Application Output) почему-то выводится сообщение: Cannot obtain a handle to the inferior: The parameter is incorrect. И ещё одна проблема. В классе FileError мне пришлось применить std::string вместо QString здесь: Код
Потому что я не могу использовать QString тут: Код
Заранее спасибо за помощь! Вот весь код проекта: text_file.pro Код
FileError.h Код
FileOpenError.h Код
FileReadError.h Код
FileWriteError.h Код
main.cpp Код
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Март 24, 2014, 16:46 Лично мне кажется, что использовать исключения для обработки чего-то из разряда
Код: if ( !file.open( QIODevice::ReadOnly ) ) { Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 24, 2014, 17:29 Затратно по времени набора кода? Но ведь классы придумали, чтобы повторно использовать код. Достаточно скопипастить себе эти классы с исключениями в следующий проект. Ну конечно, можно скопипастить showError() и перечисления с кодами ошибок.
Да, в данном случае можно было и так поступить: Код
Но я поставил себе другую задачу. Мне предложили способ обработки без исключений с применением кодов ошибок и функции showError() Я перечислил сколько есть подходов для обработки ошибок в приложениях без исключений (может их намного больше). При использовании других классов со своим способом обработки ошибок, придётся выкручиваться (см. способы обработки ошибок) Исключения унифицируют подход и делают его единообразным. Поэтому это не настолько бесполезно, как может показаться на первый взгляд. Пользователю функции readData достаточно будет написать следующий код для вывода разного рода ошибок: Код
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 24, 2014, 18:46 Моё имхо - исключение нужно выбрасывать в случае ИСКЛЮЧИТЕЛЬНОЙ ситуации. Ситуаций исключительных в которых программа может что-то сделать - по пальцам пересчитать.
Потому в %80 программ они нафиг не нужны. А 20% сделаны по привычке. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 24, 2014, 18:48 Отсутствие файла и некорректные данные в нём - это как раз примеры исключительный ситуаций. В этом случае программа может вывести текст на экран.
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 24, 2014, 19:22 Это стандартная ситуация. Такая же как отсутствие библиотек или некорректные действия пользователя. Исключительная ситуация - это ситуация, которая не предусмотрена программой.
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 24, 2014, 19:24 Это стандартная ситуация. Такая же как отсутствие библиотек или некорректные действия пользователя. Исключительная ситуация - это ситуация, которая не предусмотрена программой. Как можно выбросить исключение не предусмотренное программой? :)Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: _OLEGator_ от Март 24, 2014, 19:31 Проблема использования исключений по любому поводу - это потенциальная возможность не обработать какое-то одно исключение и программа упадет.
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 24, 2014, 19:36 Отсутствие файла и некорректные данные в нём - это как раз примеры исключительный ситуаций. В этом случае программа может вывести текст на экран. Нет, эта ситуация не является исключительной. Общее правило: если у Вас не возникает никаких трудностей с обычной/нормальной обработкой ошибки - исключение ни к чему. А вот тоже чтение из файла, Код Если ReadSomeData глубоко вложена - то скорее всего исключение уместно, т.к. слишком дорого обойдется передача ошибки "на самый верх" Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 24, 2014, 19:36 Проблема использования исключений по любому поводу - это потенциальная возможность не обработать какое-то одно исключение и программа упадет. Лучше пусть программа завершится с выводом информации о необработанном исключении, чем она будет падать с Segmentation fault. :)Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 24, 2014, 19:40 Общее правило: если у Вас не возникает никаких трудностей с обычной/нормальной обработкой ошибки - исключение ни к чему. Это что за "общее правило" такое?Это предложение набор общих слов, ничего не выражающих. Прочтите его. :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 24, 2014, 19:50 Это что за "общее правило" такое? Уймитесь :) Это предложение набор общих слов, ничего не выражающих. Прочтите его. :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 24, 2014, 19:53 Уймитесь :) Это вы уймитесь нести ерунду и называть это "общими правилами". Таких правил нет и никогда не будет, потому что это бред. :)Кстати ваш же пример с ReadSomeData это подтверждает. :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 24, 2014, 19:57 Это вы уймитесь нести ерунду и называть это "общими правилами". Таких правил нет и никогда не будет, потому что это бред. :) Библию почитайте, мелкий скандалист :)Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 24, 2014, 19:59 Библию почитайте, мелкий скандалист :) Какую библию?Я у вас уже несколько раз спрашивал, что вы под этим подразумеваете, вы всегда отмалчиваетесь. :) Ну ка, говорите, опять хабра начитались? Или видеокурсы "C++ за пять занятий" смотрели? :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 24, 2014, 21:12 Old, Igors дело говорит.
Исключение для чего нужно? Исключение это возможность проброса данных из глубины наверх. Каждый обработчик решает простое условие. "Я могу обработать данное исключение? Да - обрабатываю. Нет - пробрасываю дальше.". Для обработки, для реакции на событие. Но если обработка возможна на уровне ошибки (открытие файла) тогда исключение не нужно. Если же программа упала, значит эта ситуация не была предусмотрена разработчиками. Значит никакой информации об ошибке быть не может, ибо разработчики информации не оставили. Так называемое необработанное исключение. PS если вы мне подскажете документацию, в которой описывается как поймать "обращение по неинициилизированном указателю, выход за пределы массива, порчу памяти программы" и исправить, я буду благодарен. Для развития кругозора почитаю. PPS Segmentation fault - исключение, насколько мне известно. Цитировать В Microsoft Windows, процесс, получающий доступ к недействительным участкам памяти, создаёт исключение STATUS_ACCESS_VIOLATION Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 24, 2014, 21:46 Old, Igors дело говорит. Это ерунда. Обычная. Набор слов выданных с важным видом. :)Мы пишем функцию ReadSomeData, как нам решить использовать исключения или нет. Мы понятия не имеем, кто и когда эту функцию будет вызывать: кто-то ее позовет из main, а кто-то ее позовет из 100500 вложенной друг в друг функции. Поэтому, это выдуманное "правило" обычный бред, выданный с важным видом что-бы произвести впечатление. :) Если же программа упала, значит эта ситуация не была предусмотрена разработчиками. Значит никакой информации об ошибке быть не может, ибо разработчики информации не оставили. Так называемое необработанное исключение. Если программа упала, значит в ней содержится ошибка, а не исключительное состояние. Не надо их путать.Если программа завершилась из-за необработанного исключения, то разработчик не предусмотрел его обработку, но вся информацию по исключению есть и она передается вместе с исключением. PS если вы мне подскажете документацию, в которой описывается как поймать "обращение по неинициилизированном указателю, выход за пределы массива, порчу памяти программы" и исправить, я буду благодарен. Для развития кругозора почитаю. Еще раз, не нужно путать ошибки в программе и исключительные ситуации, это совершенно разные вещи.PPS Segmentation fault - исключение, насколько мне известно. Нет.Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 25, 2014, 07:10 PS если вы мне подскажете документацию, в которой описывается как поймать "обращение по неинициилизированном указателю, выход за пределы массива, порчу памяти программы" и исправить, я буду благодарен. Для развития кругозора почитаю. > выход за пределы массива Вот документация: http://www.cplusplus.com/reference/stdexcept/out_of_range/ Вот пример из документации: Код
По поводу обычных массивов и "обращения по неинициилизированном указателю" Это учли в современных языках программирования таких как C# и Java, в которых без исключений никуда. К сожалению, С++ не обязывает разработчиков применять исключения. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 25, 2014, 09:34 Нам всё равно придёться мириться с исключениями, так как их выбрасывают многие функции STD. Если мы их не будем отлавливать, то программы будут падать без всяких сообщений.
Я не вижу в чём принципиальная разница между двумя подходами по обработке ошибок. Чем же здесь плохи исключения? Сравните в чём разница для пользователя, который вызывает функцию readData( iFileName, arr ). Исключения выполняют, в данном случае, туже самую работу: Код
Код
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 25, 2014, 10:42 Я не вижу в чём принципиальная разница между двумя подходами по обработке ошибок. Чем же здесь плохи исключения? Сравните в чём разница для пользователя, который вызывает функцию readData( iFileName, arr ). Исключения выполняют, в данном случае, туже самую работу: Если сравнивать одно исключение с одной нормальной обработкой - то исключение куда дороже. Чего это Вы отделались печатью e.what(), где полный текст ошибки? Его надо добавлять и так просто как с ShowError не выйдет. Во-вторых, откуда предположение что только std::exception может быть испущено? Извольте ставить второй catch, если уж взялись.И главное - а кто испустит exception? Оно применяется часто именно при чтении/записи. Код Часто Вы не сможете читать "b" не проверив корректности "a" и.т.д. Общее число проверок становится невыносимым. Вот здесь разумно сделать так чтобы оператор >> испускал исключение и отловить все 1 раз наверху. Хотя и здесь некоторые предпочитают нормальную обработку. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 25, 2014, 10:52 По поводу текстов ошибок, то они внутри функции readData(). Я правильно понял замечание? Что здесь непросто?
Код
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 25, 2014, 11:04 По поводу текстов ошибок, то они внутри функции readData(). Я правильно понял замечание? Что здесь непросто? Это просто плохо, одна ф-ция и цыплят жарит, и кофе готовит и еще много чего - вот только все делает плохо :)Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 25, 2014, 11:08 PPS Segmentation fault - исключение, насколько мне известно. Нет.Цитировать Скот Мейерс в своей книге "Наиболее эффективное использование С++" утверждает, что повсеместное использование исключений в программе приведёт к снижению скорости выполнения программы на 5-10%. Исключения возникают тогда, когда некоторая часть программы не смогла сделать то, что от неё требовалось. При этом другая часть программы может попытаться сделать что-нибудь иное. Исключения позволяют логически разделить вычислительный процесс на 2 части - обнаружение аварийной ситуации и её обработка. Примечание: В принципе, ничто не мешает рассматривать в качестве исключений не только ошибки, но и нормальные ситуации, возникающие при обработке данных, но это не имеет преимуществ перед другими решениями и не улучшает структуру и читаемость программы. PS собственно и получается интересная деталь - при использовании "кода с исключениями" всегда может быть ситуация, что исключений будет типов 10-15. При использовании библиотек может доходить и до 20-30. И для обработки всех событий вам придётся писать 30 блоков обработки. А у 20 из 30 исключений внутри будут разные структуры, и это становится невыносимым :D Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 25, 2014, 11:29 Это просто плохо, одна ф-ция и цыплят жарит, и кофе готовит и еще много чего - вот только все делает плохо :) С данным примером согласен. А вот если писать свои классы исключений, то проблема с тем кто передаёт тексты ошибок - уходит: Код
К тому же, как видите, мы можем теперь передавать номер строки, в которой некорректные данные. А Тексты ошибок у нас теперь в классах: FileOpenError и FileReadError: FileOpenError.h Код
FileReadError.h Код
FileError.h Код
Пользователь теперь может вызывать функцию readData( iFileName, arr ); вот так (обрабатывая все исключения): Код
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 25, 2014, 12:07 А вот если писать свои классы исключений, то проблема с тем кто передаёт тексты ошибок - уходит: "Вообще говоря" да, но все зависит от задачи. Для такого пионерского примерчика как у Вас исключения совершенно избыточны.И главное - откуда возьмутся исключения, кто будет их генерить? Если каждый раз руками throw, то пользы немного. Обычно исключения испускают базовые ф-ции IO. Поскольку используются операторы >> и <<, то они и должны испускать. В std:: есть эта возможность, но ведь Вы работаете с Qt и вероятно будете использовать QDataStream. Как заставить его выбрасывать исключения? Да, это может за рамками темы, но это реальный вопрос. А то в Вашем обзоре все слишком уж гладко :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 25, 2014, 13:15 Речь идёт о том, какой общий подход использовать. Понятно, что этот пример очень простой и достаточно было бы написать без всяких кодов ошибок. И в таком простом примере большинство ограничилось бы простым кодом:
Код
Я же хочу проанализировать разные подходы и выбрать один. Если не применять исключений, то нужно придерживаться одного из десятков способов обработки ошибок. Один из них Вы предложили. А вот функции из других библиотек с сишным подходом будут по-другому обрабатывать ошибки. Исключения же дают единообразный подход. Если уж мы использовали подход с обработкой кодов ошибок с помощью функции showError(), то почему бы нам не использовать для этого примера свои классы исключений? Кода писать меньше, эти классы можно использовать повторно, код легко читать и изменять, а главное что это даёт единообразный подход к обработке пользовательских ошибок, как это сделано в C#, возможно и в Java (Java только начал изучать, поэтому не знаю, как там обстоят дела с исключениями) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 25, 2014, 14:20 Я же хочу проанализировать разные подходы и выбрать один. Это принципиальная и тяжелая ошибка - использовать один подход для любой задачи. Любой прием может быть очень хорош в одной ситуации, но совершенно неуместен в другой.Полагаю что исключения Вам нравятся тем что код выглядит весьма солидно (типа "грамотно" :)). Однако если за этим нет никакой содержательной части, никаких резонов - такой "дутый" код легко распознается даже программистом с небольшим опытом. Стремясь показать свою технику в отрыве от задачи Вы попадаете в неудобное положение. "догонят и еще дадут" - и правильно :) И еще: анализировать различные подходы легко и приятно. Но всегда есть противные мелочи, напр Вы работаете с Qt и вероятно будете использовать QDataStream. Как заставить его выбрасывать исключения? И я вот смотрю - Вы не горите желанием такими мелочами заниматься. А это значит что у такого работника надо стоять на душой, указывать, направлять, а он еще будет брыкаться, возражать... Это часто оказывается важнее обширных познаний и.т.п.Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 25, 2014, 14:33 Я боюсь, что если буду везде использовать подход с showError(), то будет таже самая ситуация. Опять же не вижу конкретных проблем в примере с исключениями при работе с файлами. Чем подход с showError() лучше чем подход с классами исключений?
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 25, 2014, 14:36 Я вам специально цитату привёл :) В Windows это является исключением :D Это не является исключением C++, хотя SEH и очень похож (__try, __except).:)Цитировать Скот Мейерс в своей книге "Наиболее эффективное использование С++" утверждает, что повсеместное использование исключений в программе приведёт к снижению скорости выполнения программы на 5-10%. но это не имеет преимуществ перед другими решениями и не улучшает структуру и читаемость программы. Да ну ладно. Этот пример с выходом из глубокой функции с возвратом результата хорошо это подтверждает. :)PS собственно и получается интересная деталь - при использовании "кода с исключениями" всегда может быть ситуация, что исключений будет типов 10-15. При использовании библиотек может доходить и до 20-30. И для обработки всех событий вам придётся писать 30 блоков обработки. А у 20 из 30 исключений внутри будут разные структуры, и это становится невыносимым :D Скажите честно, вы никогда не писали программ с исключениями. :)Все что вы написали выше, мягко говоря, ерунда. ;) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 25, 2014, 14:44 Я боюсь, что если буду везде использовать подход с showError(), то будет таже самая ситуация. Конечно. Ненужно зацикливаться. :)Опять же не вижу конкретных проблем в примере с исключениями при работе с файлами. Потому, что их нет.Чем подход с showError() лучше чем подход с классами исключений? Ничем, а часто он хуже.Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 25, 2014, 15:22 но это не имеет преимуществ перед другими решениями и не улучшает структуру и читаемость программы. Да ну ладно. Этот пример с выходом из глубокой функции с возвратом результата хорошо это подтверждает. :)Скажите честно, вы никогда не писали программ с исключениями. :) Все что вы написали выше, мягко говоря, ерунда. ;) 2) писал. Qt/C++/Boost/*** (секретная разработка )/OPC. Примерно 8 блоков для обработки исключений. Нет, конечно они все стандартны и можно было бы вывести строку ошибки, но... но нужно ещё кучи доп информации. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 25, 2014, 15:37 1) Читайте внимательнее. Там написано что обработка не исключительных ситуаций при помощи исключений и далее текст цитаты. Т.е. применение исключений везде даёт худший результат,чем совмещение разных подходов. Не вижу обоснований из чего это следует. :)2) писал. Qt/C++/Boost/*** (секретная разработка )/OPC. Примерно 8 блоков для обработки исключений. Нет, конечно они все стандартны и можно было бы вывести строку ошибки, но... но нужно ещё кучи доп информации. Покажите на примере и посмотрим, а было ли все так ужасно и что можно было сделать, что бы было лучше. :)Пока я вижу только попытки убедить самого себе в том, что исключения это плохо. :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 25, 2014, 15:50 Из логики следует. За сим отписываться по этой теме прекращаю, просто у вас начинается холи вар :)
PS код привести не могу, ком.тайна. Да и уволился с того места работы. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 25, 2014, 15:54 Из логики следует. За сим отписываться по этой теме прекращаю, просто у вас начинается холи вар :) Скорее это из-за того, что по теме сказать нечего из-за не владения предметом. А отписаться в теме захотелось.PS код привести не могу, ком.тайна. Да и уволился с того места работы. Другого ответа я и не ожидал. ;)Хотя я код приводить не просил, просто вымышленный пример. Ну да ладно. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Март 25, 2014, 17:39 А на сколько человечно делать грубо говоря try на весь main, чтобы не плодить код? При условии, что есть нормальная система обработки всех сгенерированных исключений? И на сколько человечно использовать исключения в конструкторах и деструкторах. Знаю, что все настоятельно рекомендуют не делать этого, т.к. исключение прерывает нормальных ход выполнения, но если использовать исключения в конце конструкторов-деструкторов после всех выполненных методов, когда мы точно уверены, что все уже ок и просто хотим получить уведомление об этом?
Хотя насчет первого понял - удобно конечно, но тогда никакой попытки обработки исключительных ситуаций на месте не будет. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 25, 2014, 18:08 А на сколько человечно делать грубо говоря try на весь main, чтобы не плодить код? При условии, что есть нормальная система обработки всех сгенерированных исключений? В main catch это последняя линия, если сюда попали, то сделать уже ничего нельзя и остается вывести диагностику и остановиться. Это ничем не отличается от вываливания в main из 100500 вложенной функции постоянно проверяю ошибку и делая return вверх.Если мы можем как то повлиять на ситуацию, то обрабатываем это в локальной секции catch. И на сколько человечно использовать исключения в конструкторах и деструкторах. В конструкторах вполне "человечно", если правильно инициализировать члены класса.В деструкторах не стоит использовать, но если понимать в чем могут быть проблемы и организационно не допускать таких случаев, то можно и в деструторах. :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 26, 2014, 19:13 Проблема использования исключений по любому поводу - это потенциальная возможность не обработать какое-то одно исключение и программа упадет. Долго думал по поводу этого тезиса, но так его и не понял. Если я написал функцию и в объявлении написал, какие исключения она выбрасывает: Код и ещё знаю, что оба эти исключения и FileOpenError и FileReadError наследуются от FileError, то могу отлавливать оба этих исключения одним блоком try/catch: Код
Таким образом исключение от меня ускользнуть не может. Большинство функции STD генерируют исключения и я так понимаю, что надо учиться все их обрабатывать. К примеру, мы выделяем память из кучи и слишком много запросили (или может случайно в цикле это начали делать). Вот такой пример из книги, когда памяти не хватает, то new выбрасывает исключение std::bad_alloc. И нам обязательно надо его обработать, чтобы программа не завершилась без всяких сообщений: Код
А если мы не хотим в данном случае получать исключения, то надо написать: new(nothrow), тогда будет возвращено: nullptr: Код
Вот только nullptr - это из C++11. А что написать вместо nullptr для C++98? Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 26, 2014, 19:16 Вот только nullptr - это из C++11. А что написать вместо nullptr для C++98? 0Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 26, 2014, 19:17 Спасибо :)
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 26, 2014, 19:17 Всегда есть шанс не вспомнить какое нибудь исключение из далёкого класса. Да, когда их 5-10-30 достаточно их все помнить. А когда их станет больше, можно и забыть. И будет "вылет без всяких сообщений".
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 26, 2014, 19:19 И будет "вылет без всяких сообщений". Неправда. В нормальных системах рантайм всегда показывает информацию о необработанных исключениях при завершении приложения.И в main нужно последним catch писать такой, который обработает любое исключение. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 08:58 С исключениями в C++ связано много ловушек. Одна из главных причин, по-моему, это совместимость с языком Си. Таких ловушек нет в C# и Java (а может они тоже есть, но их меньше). Чтобы избежать ловушек надо попробовать моделировать C# и Java.
Буду по мере познания выкладывать здесь примеры :) Пример. Ликвидация утечки памяти (из-за исключений) с помощью shared_ptr (или unique_ptr) Вот пример плохого кода, в котором из-за исключения не освобождаются ресурсы и происходит утечка памяти. Пример из книги "Professional C++", глава 10, называется пример "StackUnwinding\BadCode". В этом примере команда delete str2; не выполняется из-за того, что функция funcTwo(); выбрасывает исключение и дело до освобождения ресурса не доходит: Код
Чтобы избежать этого, можно использовать технику: Catch, Cleanup, и Rethrow (пример называется StackUnwinding\CatchAndRethrow). То есть отлавлить исключение, которое выбрасывает funcTwo(), в функции funcOne() - освободить ресурсы (delete str2;) и передать исключение дальше: Код
В Java есть сборщик мусора (как и в C#). А в C++ можно смоделировать сборщик мусора с помощью умных указателей. Писать кода меньше, его легче сопровождать, меньше вероятность допустить ошибку (забыв освободить ресурсы или забыв обработать исключение до освобождения), а так же не надо дублировать следующий код по освобождению ресурсов (delete str2;), как это было в предыдущем примере: Код
Пример с shared_ptr (или unique_ptr): Код
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: gil9red от Март 27, 2014, 09:19 А можно было не выделять память в куче в функциях, а использовать стэковую :)
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 09:27 Под строкой: "string* str2 = new string( );" надо подразумевать захват любого ресурса, а под строкой: "delete str2;" - освобождение любого ресурса :)
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Март 27, 2014, 09:37 А при чем тут совместимость с Си?
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 09:45 Си пробивает бреши в C++, в частности, в работе с исключениями (в отличае от более продуманных C# и Java): см. сборщик мусора в Java (C#) и необходимость использовать технику "Catch, Cleanup, и Rethrow" в C++ (слава Богу есть shared_ptr и unique_ptr).
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 09:49 (слава Богу есть shared_ptr и unique_ptr). Это частности техники RAII.Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 27, 2014, 10:04 Си пробивает бреши в C++, в частности, в работе с исключениями (в отличае от более продуманных C# и Java): см. сборщик мусора в Java (C#) и необходимость использовать технику "Catch, Cleanup, и Rethrow" в C++ (слава Богу есть shared_ptr и unique_ptr). Так может Вам переключиться на C# и Java? Они же "более продуманы" :)Вот Вы шпарите по книжкам вещи которые большинство форумчан давно знают. Конечно Вы не делаете ничего плохого, но и смысла пережевывать известное немного. От практического программирования все это далековато. То что Вам известны приемы/методы совсем не значит что Вы их с успехом примените. "Вот я побольше выучу, и тогда..." - это ошибка многих. Программирование не было и не будет эксплуатацией памяти (и это хорошо и правильно :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Март 27, 2014, 10:10 Си пробивает бреши в C++, в частности, в работе с исключениями (в отличае от более продуманных C# и Java): см. сборщик мусора в Java (C#) и необходимость использовать технику "Catch, Cleanup, и Rethrow" в C++ (слава Богу есть shared_ptr и unique_ptr). В си вообще как таковых исключений нет. А насчет сборщика мусора в С++ вот Цитировать Надо отметить, что автоматическая сборка мусора не включена в стандарт C++ по той простой причине, что программа, её использующая, будет всегда работать медленнее, чем если бы сборка мусора не использовалась вообще. Поэтому Бьёрном Страуструпом было предложено перепоручить обязанности сборки мусора внешним библиотекам, не затрагивая самого C++, что может позитивно сказаться на производительности приложений, поскольку программист сам может решить, где и когда ему стоит использовать автоматическое управление памятью. Это и является серьёзным отличием С++ от Java – при использовании Java у программистов просто нет выбора. А вот и пример сборщика мусора на С++ http://www.rsdn.ru/article/cpp/GCcpp.xml Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 10:29 Цитировать Надо отметить, что автоматическая сборка мусора не включена в стандарт C++ по той простой причине, что программа, её использующая, будет всегда работать медленнее... Это было актуально в те далёкие времена. Сейчас и копьюторы стали намного мощнее и сам Java сравнялся с C++ в плане скорости. Вопрос не в этом, чтобы переходить на другой язык, где есть сборщик мусора, а чтобы отработать полезную привычку писать осознанно и правильно и создавать надёжные программные системы. Использовать техники доступные в C++, чтобы приблизиться к тому идеалу, к которому подошли C# и Java (в плане безопасности программирования). P.S. Вроде C# обязан языку "Оберон/Компонентный Паскаль" (в плане безопасности программирования). Вот статейка про выход за пределы границ массива: http://www.inr.ac.ru/~info21/blackbox/disciplina/arr_bounds_checks.htm Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 27, 2014, 10:36 Кхм. Выражу сомнения в возможности Java обрабатывать данные с 4 оптических интерфейсов без 100% загрузки процессора :D
PS не стоит думать "да немного медленнее и что с того"? Этих немного медленнее много. Сотни можно сказать :D Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Март 27, 2014, 10:48 Thank God I've never seen operating systems written on Java or C# ;D ;D ;D
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 27, 2014, 11:14 Надо отметить, что автоматическая сборка мусора не включена в стандарт C++ по той простой причине, что программа, её использующая, будет всегда работать медленнее... Дело не в быстрее/медленнее (это "простое" объяснение для широкого круга). Автоматическая сборка мусора противоречит духу/концепциям С/С++.Вопрос не в этом, чтобы переходить на другой язык, где есть сборщик мусора, а чтобы отработать полезную привычку писать осознанно и правильно и создавать надёжные программные системы. Использовать техники доступные в C++, чтобы приблизиться к тому идеалу, к которому подошли C# и Java (в плане безопасности программирования). Пока что НИ РАЗУ выученное не было применено удачно, к месту :) Ладно, будем надеяться что "и это пройдет"Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 11:37 Пока что НИ РАЗУ выученное не было применено удачно, к месту :) Ладно, будем надеяться что "и это пройдет" Как это ни разу? А я же заменил showError() с помощью своих классов исключений :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 27, 2014, 12:02 Как это ни разу? А я же заменил showError() с помощью своих классов исключений :) Так это классический анти-паттерн - как НЕ НАДО использовать исключения :)С книжками/изучением у Вас все отлично, но как только начинаете это тулить куда ни попадя - смех и грех. Без практики теория довольно беспомощна :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 12:16 Почему же их не использовать для обработки ошибок? Хотя бы на примере чтения из файла.
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 27, 2014, 13:16 Почему же их не использовать для обработки ошибок? Хотя бы на примере чтения из файла. Использовать, и для чтения из файла - часто. Только Вы их неправильно используете, о чем я в этой теме уже говорил дважды - и даже рядом тему создал.Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 13:30 Почему же их не использовать для обработки ошибок? Зачем вы спрашиваете чье то мнение? У вас сейчас пока еще есть возможность изучать и исследовать все, на что падает ваш взгляд. Воспользуйтесь этим. Скоро вас загонят в корпоративные рамки, где скажут использовать это и это, а это не использовать, а с этим делать так и никак иначе. :)В эти свободные времена, вам нужно постараться максимально расширить ваш технических кругозор. В дальнейшем, вы сможете сразу определять, в какие стороны можно посмотреть, что бы решить задачу. Не слушайте никого: вам говорят так не делать - сделайте так, почувствуйте проблему или поймите что ее там нет и все это предрассудки. Пробуйте, творите, выкладывайте здесь, будем обсуждать. :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 13:47 Спасибо огромное! Согласен! Отлично сказано, что надо сделать и самому почувствовать проблему или её отсутствие :)
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 13:59 Как это ни разу? А я же заменил showError() с помощью своих классов исключений :) А где на это можно посмотреть?Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 14:07 Как это ни разу? А я же заменил showError() с помощью своих классов исключений :) А где на это можно посмотреть?Приведу сразу все примеры: Пример без исключений: Код
Пример с исключениями Код
Пример со своими классами исключений text_file.pro Код
FileError.h Код
FileOpenError.h Код
FileReadError.h Код
FileWriteError.h Код
main.cpp Код
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 27, 2014, 14:15 Код
Код Конечно это надо подготовить (возможно классами) - но оно того стоит Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 14:23 Вы не могли бы подробнее написать. Набросками. Как этот код в классы убрать?
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 27, 2014, 14:26 Можно проще написать - так как в Qt разработчики отказались от исключений, то для их внедрения вам придётся переписать большую часть Qt. :D А это бессмысленно.
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 14:27 Вот функция main из одного моего небольшого проекта
Код
Если где-то внутри я могу повлиять на работу программы при возникновении исключения, то там имеем локальный блок try-catch для интересующих в данный момент исключений. Выпали в main, значит все что мы можем, это сохранить в лог всю доступную информацию и выйти. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 14:30 Можно проще написать - так как в Qt разработчики отказались от исключений, то для их внедрения вам придётся переписать большую часть Qt. :D А это бессмысленно. Да, очень жаль, что когда Qt начинали разрабатывать не было ни одного компилятора, умеющего их нормально. Вот теперь пожинаем. :(Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 27, 2014, 14:34 to Old:
У вас всё сводится к логированию и выходу из программы. Я же имел в виду восстановле ние работоспособности программы :) Но фу фу - не буду спорить. В качестве "падает тихо" пойдёт :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 14:37 Вы не могли бы подробнее написать. Набросками. Как этот код в классы убрать? Смысл в том, что бы было возможно писать так:Код В этом случае, логика чтения/записи не захламляется проверками. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Март 27, 2014, 14:42 Можно проще написать - так как в Qt разработчики отказались от исключений, то для их внедрения вам придётся переписать большую часть Qt. :D А это бессмысленно. Зато разработчики STD и Boost активно их используют. Надо отлавливать все исключения, как и проверять коды функций на случай если они отработали неверно. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 14:43 Я же имел в виду восстановле ние работоспособности программы :) Плохо, что вы не читаете сообщения, там в последнем предложении все написано.Хотите и знаете как восстановиться, используете локальный блок. Или вам нужен пример, в каких случаях программа может восстановиться при исключении? Так их есть у меня. :) Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 27, 2014, 14:56 Вы не могли бы подробнее написать. Набросками. Как этот код в классы убрать? Для чтения int используйте http://www.prog.org.ru/index.php?topic=26733.msg192575#msg192575 (http://www.prog.org.ru/index.php?topic=26733.msg192575#msg192575) Только замените QDataStream на QTextStream. Чтение вектора допишете (наск помню его в QTextStream нет)Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 15:45 Я же имел в виду восстановле ние работоспособности программы :) Появилось немного времени, хочу поделится своими мыслями про исключения и восстановления. :)C++ промышленный язык и сделан для создания больших и сложных систем. Любая большая система состоит из кучи маленьких, в идеале независимых подсистем. Возьмем для примера одну из таких подсистем, пусть это будет менеджер ресурсов. В задачи этой подсистемы может входить загрузка и распределение ресурсов. Пусть на входе, она будет получать путь к директории с файлами ресурсов. Код При конструировании менеджера проверяется указанная директория и если там нет данных программы (или вообще нет такой директории), то выбрасывается исключение BadDataDir. А теперь давайте посмотрим: фатальная ли это ситуация, когда в указанной директории нет файлов с данными? Для менеджера ресурсов несомненно да, его существование бессмысленно с неверным директорием. А для всей системы в целом? Да это ерунда. Система может искать данные в директории пользователя, в общих директориях, короче, в куче разных мест. И если система начала создавать менеджер ресурсов для одного источника и там не оказалось данных (получили исключение), то она может попробовать создать еще 100500 таких менеджеров, пробуя все известные ей источники. Код
Поэтому, исключение в программе это вовсе не какая то трагедия, а штатная ситуация, которую можно легко обрабатывать. Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Igors от Март 27, 2014, 16:28 то она может попробовать создать еще 100500 таких менеджеров, пробуя все известные ей источники. Весьма вероятно что такой класс будет синглтоном. Если же хотите иметь 2 или более менеджера ресурсов - то расскажите порядок загрузки ресурса, какой менеджер должен юзаться? А смысла в исключениях здесь не вижу никакого - просто проверить существование фолдера/файла и не подавать его в конструктор, а сделать метод напр SetDir Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 16:37 Весьма вероятно что такой класс будет синглтоном. Если же хотите иметь 2 или более менеджера ресурсов - то расскажите порядок загрузки ресурса, какой менеджер должен юзаться? Упаси Бог. Никаких синлтонов. Тем более для менеджеров ресурсов.Я могу иметь 100500 источников с данными и для каждого источника иметь свой менеджер. В одном хранить картинки, в другом звуки. Могу иметь несколько источников с картинками. Порядок поиска ресурсов может быть любой, хоть случайный. :) Или сделать приоритеты для менеджеров и искать сначала в более приоритетных источниках (главный системный и addon'ый). Это детали реализации конкретной системы, причем очень мелкие детали. просто проверить существование фолдера/файла и не подавать его в конструктор, а сделать метод напр SetDir Не вижу в этом никакого смысла. Кто то еще должен знать как это проверять, для чего? Пусть этим занимается менеджер ресурсов. Только он должен знать как проверить наличие и целостность данных.Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Март 27, 2014, 16:40 Сегодня наткнулся на ситуацию, когда попытка delete вызывает исключение, но оно не ловится даже если стоит catch(...), а ловится в дебаггере. Почему так?
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Old от Март 27, 2014, 16:49 Сегодня наткнулся на ситуацию, когда попытка delete вызывает исключение, но оно не ловится даже если стоит catch(...), а ловится в дебаггере. Почему так? Скорее всего дебагер имеет ввиду не C++ исключение, а системное. Скорее всего где то бьете память.Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Март 27, 2014, 16:53 Да там просто память была заблокирована.
А как же ловить системные исключения? Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Март 27, 2014, 16:54 Вызывается системное исключение. Оно ловится __try __еxcept, но зачастую его ловля бессмысленна :D Стек бьётся в 50% случаев.
Название: Re: Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Март 27, 2014, 16:58 Вызывается системное исключение. Оно ловится __try __еxcept, но зачастую его ловля бессмысленна :D Стек бьётся в 50% случаев. thanks)Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Апрель 12, 2014, 08:19 В начало темы добавил итог темы (с датой), чтобы если кто-то случай зайдёт, то ему не пришлось бы долго выискивать этот итог.
Итог темы. Добавил: Апрель 12, 2014, 09.10 Долго для себя выбирал стратегию ловли ошибок. Остановился на исключениях. Точнее даже на создании своих классов исключений, которые наследуют стандартные: http://i.pixs.ru/storage/2/3/2/171png_9973242_11655232.png Настоятельно рекомендую прочитать главу "Chapter 10. Handling Errors" (особенно параграф "Writing Your Own Exception Classes") из книги: Название: Professional C++ Год: 2011 Автор: Marc Gregoire, Nicholas A. Solter, Scott J. Kleper Количество страниц: 1104 Язык: английский Скачать: http://kickass.to/wrox-professional-c-plus-plus-2nd-edition-2011-retail-ebook-debt-t7461950.html Исходники: http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449,descCd-DOWNLOAD.html Специально для демонстрации сделал два примера со стратегиями: - с исключениями (как в книге выше): https://github.com/8Observer8/FiveAndFive - без исключений: https://github.com/8Observer8/text_file Стратегию "без исключений" мне подсказал "Igors". P.S. Здесь проект как тестировать класс с исключениями FiveAndFive (выше). Только надо чтобы папки с проектами FiveAndFive и FiveAndFiveTests лежали в одном каталоге. Этот проект создаётся в Qt 5.2.1 так: File -> New File or Project... -> Other Project -> Qt Unit Test: https://github.com/8Observer8/FiveAndFiveTests (https://github.com/8Observer8/FiveAndFiveTests) Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: OKTA от Апрель 14, 2014, 10:16 Спасибо, 8Observer8, за информацию!
Я понял причину неприязни многих людей к исключениям и свою в том числе) Проблема исключений не в том, что лень писать лишний код, а в том, что методология return гораздо проще и понятнее логически, чем исключения. Я ради интереса сейчас намерен включить исключения в свой текущий проект и столкнулся с тем, что вот так просто не перепишешь под исключения имеющийся код, особенно когда хочешь использовать исключения не только как замену Return и удобный вывод ошибок пользователю, но и как средство для возможного решения проблем на месте. Немного ломается привычный подход) Но ничего, сделаю) Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Апрель 14, 2014, 11:19 Рад, что пригодилось! Разведка сработала нормально :)
Отмечу ещё такую очень важную особенность, которую я прочувствовал до костей. Если выбрасывать стандартные исключения, то текст вывода будет дублироваться и такой подход очень НЕгибкий, так как ничего кроме текста не выбросишь. Вот пример: Код
"std::out_of_range" и "std::invalid_argument" наследуют от std::logic_error, поэтому надо делать свой класс LogicError и наследовать его от std::logic_error. Текст ошибки будет формироваться в пользовательских классах OutOfRange и InvalidArgument, которые наследуют от LogicError. То есть текст ошибки только в одном месте. К примеру, если мы выбрасываем OutOfRange, то можем указать сам аргумент и в какой диапазон он не попал. Вот вызов программы сложения двух целых чисел. Мы можем отлавливать оба пользовательских исключения (OutOfRange и InvalidArgument) одним блоком catch ( const LogicError &e ): Код
Реализация: Код
Я к тому, что обязательно надо писать свои классы исключений, так как они гибкие. P.S. На всякий случай, в моём примере из предыдущего сообщения (FiveAndFive) - я это реализовал. Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Октябрь 15, 2014, 07:25 Использую стратегию из этой книги: http://www.amazon.com/Professional-C-Marc-Gregoire/dp/0470932449
Output Цитировать Error: divide by zero in the function func() main.cpp Код
DivideByZero.h Код
AnotherError.h Код
LogicError.h Код
Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: Авварон от Октябрь 17, 2014, 09:10 Позанудствую - использовать исключения в программах на Qt чревато, так как Qt не только не использует исключения в своём API, но еще и некорректно обрабатывает пользовательские исключения, пролетевшие через кутешный код. К примеру, будет утечка в QVector, если конструктор Т кинет исключение. Писать правильный код с исключениями очень и очень сложно (std контейнеры - тому пример), поэтому, имхо, лучше их не использовать.
В свете с++11 мне очень нравится подход с maybe-типом (ака std::experimental::optional) - когда ф-ия возвращает либо значение, либо пустоту. Этот подход расширяется введением класса Error/Result (T value + bool ok + StringType errorString). В отличие от исключений, нам приходится учитывать, что ф-ия может вернуть ошибку и нет возможности пробросить её наверх, что, кмк, весьма удобно (вот если бы в с++ был жавовский спецификатор throws...). Ну и нет проблемы что у нас что-то пролетело из нижележащего кода, что нас поломало. Upd: Вернее, возможность пробросить ошибку наверх как раз есть, только это приходится делать явно. Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Октябрь 17, 2014, 20:23 Цитировать К примеру, будет утечка в QVector, если конструктор Т кинет исключение. Ничего не понял. А в std::vector может быть аналогичная ситуация? Что такое T?Цитировать Писать правильный код с исключениями очень и очень сложно (std контейнеры - тому пример) Не уверен, что правильно понимаю. То есть std контейнеры неудачны, так как в определённых ситуациях выбрасывают исключения, а Qt контейнеры не выбрасывает? Отсюда следует, что для того чтобы писать правильный код нужно полностью отказаться от std контейнеров? Qt контейнеры на 100 % заменяют std контейнеры?Допустим есть такой код на std::vector, который позволяет контролировать выход за пределы массива: Код
Если я использую этот код в Qt программе, что мне за это будет? Почему я не могу использовать исключения аккуратно? Почему именно "лучше их не использовать"? Извините за возможно глупые вопросы, но я начал изучать профессионально C++ и Qt только в этом году Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Октябрь 17, 2014, 21:29 Qt написан без исключений и без возможности их применения.
Т.е. могут возникнуть десятки и сотни утечек/ошибок в внутренностях Qt. Собственно надо следовать мудрости Страуструпа - "Всегда писать с исключениями или без них, не смешивая". Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Октябрь 18, 2014, 08:32 Qt написан без исключений и без возможности их применения. Не понимаю. Причём тут "Qt написан без исключений"Т.е. могут возникнуть десятки и сотни утечек/ошибок в внутренностях Qt. "без возможности их применения. " Как так? Я же могу применять. Позволяет Я выбросил исключение из функции и я же его обработал. О чём вы говорите? Вообще не понимаю Код
Код
Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Октябрь 18, 2014, 10:05 У меня ещё такой вопрос. Можно ли считать огромной оплошностью разработчиков Qt, что они разрешили использовать в программах на Qt функции из C++11 для перевода из строки в число? Может надо было вообще запретить ключевые слова try, catch, throw? Или хотя бы выдавать предупреждения?
Вот пример кода на C++11. Здесь я обязан отлавливать исключения, так как получу крэш, если пользователь введёт буквы вместо цифр (в этом случае функция std::stod() выбрасывает исключения std::invalid_argument и std::out_of_range) Код
Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Октябрь 18, 2014, 11:12 Они рекомендуют не использовать исключения.
Если вы их используете - вы берёте на себя ответственность за поведение программы :) Так то если не мешать Qt классы и исключения, то вполне всё работает и не сбоит. Вы можете спрыгнуть с 130 этажа, но создатель объекта "человек" не предусматривал такую ситуацию и поведение будет непредсказуемым :D offtop: были случаи выживших при падении с 10к метров. Так что это действительно неопределённое поведение :) Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: 8Observer8 от Октябрь 18, 2014, 11:43 Исключения - это большая ответственность, но при этом собственные классы исключений очень облегчают разработку!
Написал небольшую статью: Стратегия обработки ошибок пользователя с помощью собственных классов исключений (http://www.prog.org.ru/topic_27797_0.html) Название: Re: [РЕШЕНО] Обработка ошибок без исключений и с помощью исключений Отправлено: Bepec от Октябрь 18, 2014, 16:50 Вы не написали статью. Вы написали сообщение с ссылками. Почитайте на досуге чем они отличаются :D
|