crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Qt & C++ :: Обработка ошибок и отладка сложных проектов
Majestio
  опции профиля:
сообщение 5.7.2013, 13:04
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 67
Регистрация: 13.2.2013
Пользователь №: 3710

Спасибо сказали: 1 раз(а)




Репутация:   1  


Вобщем вопрос встал совсем уж конкретно. Суть в следующем:

В простейших программах написал проверку, вывел сообщение, если есть возможность обработать, обработал. Все понятно и прозрачно. Но когда программа вырастает в достаточно большой проект, когда стек вызова вырастает до 10-15 вложенных процедур (а при этом количество созданных экземпляров классов от 50), начинает съезжать крыша. Ну хорошо, программу худо бедно assert'ами и qDebug'ами отладил. Дальше начинается ввод в эксплуатацию, и там явно будут ошибки. Сообщение "Ошибка при работе с базой данных" не скажет ровным счетом ничего.

Далее опишу моменты, которые у меня сейчас встречаются, и которые я обрабатываю "как умею"

Вопрос 1. Поиск ошибок в коде

Использую __FILE__ и __LINE__ . Они указывают место в коде. Но есть "но". См "псевдо-код":

1) если (!процедура_удаления_старых_данных) вывести уведомление

2) процедура_удаления_старых_данных
{
2.1) открыть транзакцию
2.2) заблокировать на update нужные записи
2.3) удалить записи
2.4) закоммитить транзакцию
2.5) записать изменения в служебную таблицу-лог
}

Допустим на шаге 2.3 рвется связь с базой. Естественно БД самостоятельно откатывает транзакцию. Хорошо, мы отработали проверку и вывели ошибку - "ошибка удаления записей". Вопрос - в каком объекте, удаление каких данных, и пр. В идеале бы хотелось мы видеть весть стек вызова со всеми параметрами.

Пока решил примитивным способом - вывел все операции с базой в класс с глобальной видимостью. В классе определил QString Error. Если метод класса отрабатывает с ошибкой, он в эту переменную пишет подробности. В коде использую макросы:

#define GuiCheckContinue()     if (Global.Error!="") { QMessageBox::warning(0, QObject::tr("Внимание!"), Global.Error + QObject::tr("<hr>Файл: \"")+QFileInfo(__FILE__).fileName()+QObject::tr("\"<BR>Строка: ")+QString::number(__LINE__)); qCritical() << Global.Error + QObject::tr(" Файл: \"")+QFileInfo(__FILE__).fileName()+QObject::tr("\" Строка: ")+QString::number(__LINE__); Global.Error="";}

#define GuiCheckReturn()     if (Global.Error!="") { QMessageBox::warning(0, QObject::tr("Внимание!"), Global.Error + QObject::tr("<hr>Файл: \"")+QFileInfo(__FILE__).fileName()+QObject::tr("\"<BR>Строка: ")+QString::number(__LINE__)); qCritical() << Global.Error + QObject::tr(" Файл: \"")+QFileInfo(__FILE__).fileName()+QObject::tr("\" Строка: ")+QString::number(__LINE__); Global.Error=""; return; }


В коде это выглядит примерно так:

if (!Global.DataQuery.exec()) { 
  GuiSqlErrorData("Ошибка при работе с БД!");
  Global.RollbackTransaction();
  GuiCheckContinue();
  return;
}
Global.CommitTransaction();                     GuiCheckReturn();
Global.DelLocker("Rubricator",Num);             GuiCheckReturn();
Global.SetOperation("Rubricator",Num,3,"");     GuiCheckReturn();
Global.Notify("Rubricator","*");                GuiCheckReturn();


Выводится в случае ошибки нечто, типа:



Вобщем меня это как-то не устраивает. Какие есть мысли?

Вопрос 2. Обработка отката занятых ресурсов в случае ошибки

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

Если есть желание, подумайте над "простеньким" вопросом. Вот типичный алгоритм:

1) Открыли транзакцию
2) Заблокировали запись
3) Занесли информацию с служебную таблицу - кто заблокировал и на какую операцию
4) Отредактировали запись
5) Закоммитили транзакцию
6) Удалили инфу о вашей блокировке
7) Записали в журнал операций что вы сделали с записью

На шагах 1-2-4-5 используется первое соединение с базой, с 3-6-7 второе (назовем служебное). Чтобы "служебные" операции не попадали в транзакционный блок. Теперь представим случай, на шаге 5 связь с СУБД рвется, коммит не прошел. Что делать дальше?

Вощем буду рад любым идеям :rolleyes:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.7.2013, 15:44
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Majestio @ 5.7.2013, 15:04) *
Не знаю почему, но в Qt почему-то не принято пользоваться исключениями.
В Qt подавляющее большинство функций, возвращают осмысленные значения (удалось что-то сделать или нет), поэтому нужды в исключениях почти нет.
Есть соображение, что исключения нужно кидать из конструкторов объектов (когда в конструкторе происходят потенциально опасные вещи, а всё подряд проверять не выгодно), чтобы в вызывающем коде это перехватить.

Вообще я вижу что ты сам наплодил монстра и не понимаю зачем и непонятна суть проблемы.

Цитата(Majestio @ 5.7.2013, 15:04) *
1) Открыли транзакцию
2) Заблокировали запись
3) Занесли информацию с служебную таблицу - кто заблокировал и на какую операцию
4) Отредактировали запись
5) Закоммитили транзакцию
6) Удалили инфу о вашей блокировке
7) Записали в журнал операций что вы сделали с записью

Цитата(Majestio @ 5.7.2013, 15:04) *
Теперь представим случай, на шаге 5 связь с СУБД рвется, коммит не прошел. Что делать дальше?
честно сообщить об этом пользователю (например, послав сигнал в GUI)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 27.4.2024, 12:24