Russian Qt Forum
Ноябрь 23, 2024, 09:55 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Как пользоваться исключениями  (Прочитано 9106 раз)
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« : Июнь 15, 2015, 20:07 »

Привет, друзья!
Я никогда не пользовался исключениями, но хотел бы научиться.
Как они работают и синтаксис я понял. Не ясно вот что:
Что принято бросать в какой ситуации? Допустим, у меня нет указанного файла, что бросать?
Есть ли смысл наследоваться от стандартных классов, QException. Нужно ли придумывать и указывать код ошибки?
Оно нужное дело вообще или можно статусами обойтись?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #1 : Июнь 15, 2015, 20:20 »

Не используйте исключения в кутешном коде.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Июнь 16, 2015, 09:27 »

Оно нужное дело вообще или можно статусами обойтись?
Однозначно нужное, хотя бы потому что это штатное средство языка. А вот насколько - есть разные мнения. Я стараюсь всегда обойтись кодом ошибки до тех пор пока необходимость исключений не станет очевидной. Другие наоборот, используют исключения при первой возможности.

Что принято бросать в какой ситуации? Допустим, у меня нет указанного файла, что бросать?
Есть ли смысл наследоваться от стандартных классов, QException. Нужно ли придумывать и указывать код ошибки?
Да на все вопросы. Опять-таки насколько нужно размазывать классы исключений - дело вкуса/стиля. Пример
Код
C++ (Qt)
if (что-то не связалось)
throw MyException("Line %d: invalid syntax", lineNomer);
 
Испускающий не знает имени файла при чтении которого произошла ошибка - зато прекрасно знает что случилось
Код
C++ (Qt)
try {
DoReadFile(...);
}
catch (MyException & e) {
ShowError("Error reading " + fileName + ": "  + e.errorText());
}
catch (...) {
ShowError("Unknown error reading " + fileName);
}
Ловящий наоборот, имя файла знает, но что конкретно случилось - нет. Вот и комбинируйте
Записан
Akon
Гость
« Ответ #3 : Июнь 19, 2015, 15:30 »

Я широко использую исключения в Qt-приложениях. Ho! Нужно понимать как будет проходить исключение через код Qt, и что этот код делает при наличии исключения. Во многих случаях код Qt просто не рассчитан на возможное наличие исключения, и вы можете получить утечку памяти, крах, или неопределенное поведение.

Одни участки Qt-кода могут быть адаптированы (перекрытие виртуальных методов) вами для корректной работы с исключениями, например, если вы выбросите исключение из QAbstractItemModel::setData(), то у вас завалится любой делегат из Qt, но вы можете сделать свой класс делегата с соответствующей функцией.

Другие - могут быть относительно легко адаптированы с помощью патчинга сорцов Qt с последующей перекомпиляцией, например, я делал патчинг QObject::activate() с целью выбрасывать исключения из слотов с дефолтным показом сообщения и без разрыва вызова цепочки слотов.

С третьими - по большому счету никак.

В основном, исключения больше пронизывают ваш код, чем Qt. Наследовать исключения лучше от std::exception, все ошибки времени выполнения - от std::runtime_error. При использовании исключений вместа кода ошибки (категории кода ошибки) используется тип исключения. Все std-исключения минимально функциональны (хотя их функций достаточно во вногих случаях), например, нет метода clone() или цепочки вложенных исключений. Также, в boost есть кроссплатформенная либа для работы с системыми (OS API) ошибками через исключения.

P.S.
Исключение - это просто альтернативное ветвление алгоритма с побочными (нужными) действиями. Ничего особенного.

Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #4 : Июнь 19, 2015, 18:15 »

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

Очень удобно, да:(
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #5 : Июнь 21, 2015, 12:33 »

спасибо. Достаточно подробно.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #6 : Июнь 27, 2015, 13:35 »

Не используйте исключения в кутешном коде.
А как действовать в случае использования сторонней библиотеки, в которой на каждый чих генерируется исключение?
Я столкнулся с этим MQTT C++ Client. Пробовал вызовы функций библиотеки делать через обработку всех исключений, например:
Код:
try{
  client.subscribe(subTopic, QOS, nullptr, subListener);
}catch(...){
}
не помогает, программа валится.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Akon
Гость
« Ответ #7 : Июнь 27, 2015, 16:26 »

Потому что ABI получился различным. Что в либе (dwarf, sjlj), и что в программе?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Июнь 27, 2015, 17:21 »

Потому что ABI получился различным. Что в либе (dwarf, sjlj), и что в программе?
Вот когда знатоки бросают такие фразы... ну я прямо теряюсь Улыбающийся Вот мои скудные познания

ABI - набор правил/соглашений по вызовам (типа что на каком регистре ожидает callee). Как он может "получаться" различным Непонимающий  Либа может быть совместима по ABI или нет - и тогда ее никак не приспособить.

dwarf - видел в установках, формат отладочной информации

sjlj - никогда не слыхал о таком

Растолкуйте плиз что я не так понимаю. Спасибо
Записан
Akon
Гость
« Ответ #9 : Июнь 27, 2015, 18:02 »

Когда вы пишите try/catch компилятор создает дополнительные служебные структуры данных, помещаемые на стеке (или еще в каких секциях). Если исключение переходит  границу модулей, то формат этих структур должен быть идентичен для этих модулей. Для поддержки исключений компилятор может использовать разные механизмы, например, MSVC использует SEH - это вообще механизм ОС. В этом случае, например, throw в конечном счете трансформируется в вызов API RaiseException, а catch - в соостветствующие фильтры __except. Как вы понимаете, это все ABI.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #10 : Июнь 27, 2015, 22:44 »

Когда вы пишите try/catch компилятор создает дополнительные служебные структуры данных, помещаемые на стеке (или еще в каких секциях). ...
Круто. И библиотека, и программа, использующая библиотеку, собраны одним компилятором - mingw.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Akon
Гость
« Ответ #11 : Июнь 27, 2015, 23:30 »

Вы сами собирали?
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #12 : Июнь 28, 2015, 14:13 »

Вы сами собирали?
Да.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Akon
Гость
« Ответ #13 : Июнь 28, 2015, 14:56 »

А при каком типе исключения валится? Если вставить в самое начало ф-ии
client.subscribe(subTopic, QOS, nullptr, subListener);
throw std::exception();
что будет?
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #14 : Июнь 28, 2015, 17:00 »

На этом типе и валится:
terminate called after throwing an instance of 'mqtt::exception'
  what():  std::exception

Но сейчас вставлю в функцию throw, посмотрим.
upd: все то же самое.
« Последнее редактирование: Июнь 28, 2015, 17:17 от sergek » Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.183 секунд. Запросов: 22.