Название: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: Majestio от Июль 05, 2013, 13:17 Вобщем вопрос встал совсем уж конкретно. Суть в следующем:
В простейших программах написал проверку, вывел сообщение, если есть возможность обработать, обработал. Все понятно и прозрачно. Но когда программа вырастает в достаточно большой проект, когда стек вызова вырастает до 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. Если метод класса отрабатывает с ошибкой, он в эту переменную пишет подробности. В коде использую макросы: Код
В коде это выглядит примерно так: Код: if (!Global.DataQuery.exec()) { Выводится в случае ошибки нечто, типа: (http://i48.fastpic.ru/big/2013/0705/cf/0ca883d1fef68f7b3b1661da3d3d85cf.png) Вобщем меня это как-то не устраивает. Какие есть мысли? Вопрос 2. Обработка отката занятых ресурсов в случае ошибки Не знаю почему, но в Qt почему-то не принято пользоваться исключениями. Без них данный вопрос вообще выглядит каким-то монстром. В приведенном выше коде, как вы заметите - с этим явно не чисто. Я пока еще в раздумиях. Если есть желание, подумайте над "простеньким" вопросом. Вот типичный алгоритм: 1) Открыли транзакцию 2) Заблокировали запись 3) Занесли информацию с служебную таблицу - кто заблокировал и на какую операцию 4) Отредактировали запись 5) Закоммитили транзакцию 6) Удалили инфу о вашей блокировке 7) Записали в журнал операций что вы сделали с записью На шагах 1-2-4-5 используется первое соединение с базой, с 3-6-7 второе (назовем служебное). Чтобы "служебные" операции не попадали в транзакционный блок. Теперь представим случай, на шаге 5 связь с СУБД рвется, коммит не прошел. Что делать дальше? Вощем буду рад любым идеям ??? Название: Re: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: Авварон от Июль 05, 2013, 19:46 Не знаю почему, но в Qt почему-то не принято пользоваться исключениями. Исключения в Qt не используются по историческим причинам - когда АПИ появлялось, поддержка исключений в компиляторах была не полной. Но внутри какой-то отлов исключений присутствует - с большой вероятностью, выброшенное исключение ничего не поломает. Так что никто не мешает их использовать в вашем коде. Другое дело, сможете ли вы написать код, безопасно работающий, не оставляющий приложение в не пойми каком состоянии?:) Название: Re: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: navrocky от Июль 08, 2013, 14:27 Исключения можешь использовать в своем коде, но не пропускать прохождение исключения через qt-шные недра и код сторонних библиотек. К примеру, код внутри слота надо обернуть в try/catch, иначе программа может грохнуться.
На самом деле, qt может быть собран с поддержкой исключений, тогда можно пулять исключения и в слотах. Но тогда тебе надо таскать с собой свою сборку qt, т.к. в некоторых ОС qt собирают без поддержки исключений и там приложение тупо вылетает. А для crash report существуют готовые решения, google breakpad, например. Подскажу еще одну хорошую практику формирования отладочного вывода от себя. Когда растыкиваешь отладочный вывод по коду частенько возникает проблема - лень что-то писать внятное, особенно когда это мелкая проверка, редко срабатывающая. Обычно в таких случаях ставят assert или какой-нибудь check, который будет также работать в релизе. Этот assert генерирует сообщение с условием, именем файла и номером строки. А теперь, предположим, у клиента старая программа и он вам присылает лог программы, а в новом коде уже и таких файлов нет, а может строки уже хорошо сместились. Я для себя сделал простейший генератор гуидов и растыкиваю по коду именно эти гуиды + сообщение (опционально). Гуиды позволяют почти со 100% точностью найти нужный кусок кода куда бы он не переместился. Также гуиды позволяют построить словарь, с расшифровкой ошибки, в который можно будет вносить внятные сообщения пользователю для каких-то "популярных" ошибок. Еще один плюс гуида - можно очень быстро найти это место в проекте (поиск по исходникам в IDE). Я для себя сделал маленький скриптец генерации гуида вида "<91dd34f1>" на пистоне: Код В QtCreator добавил его в External Tools с вызовом по горячей кнопке. Очень удобно. Код
Надеюсь кому-то это пригодится. Спасибо за внимание. Название: Re: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: navrocky от Июль 08, 2013, 14:39 По поводу сбора стека вызовов есть идея оборачивать код в критических местах в try/catch, в котором накапливать строку стека вручную и отпускать исключение дальше. Для облегчения можно наваять макрос.
Код
Если каждый уровень пометить гуидом :), тогда можно для определенных "снимков" вида "<43c25203>,<3c36be6c>,<f43cbce8>,<0c3e5a79>,<1ac698c4>" сформировать внятные сообщения. Грубо говоря, примерно так: Код
Название: Re: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: kamre от Июль 08, 2013, 16:42 А теперь, предположим, у клиента старая программа и он вам присылает лог программы, а в новом коде уже и таких файлов нет, а может строки уже хорошо сместились. Разве сложно достать из контроля версий по тэгу или ревизии из лога нужную версию исходников, которая соответствует той сборке, что была у клиента?Название: Re: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: panAlexey от Июль 08, 2013, 17:58 Подскажу еще одну хорошую практику формирования отладочного вывода от себя. Когда растыкиваешь отладочный вывод по коду частенько возникает проблема - лень что-то писать внятное, особенно когда это мелкая проверка, редко срабатывающая. Обычно в таких случаях ставят assert или какой-нибудь check, который будет также работать в релизе. Этот assert генерирует сообщение с условием, именем файла и номером строки. Использую такую-же технику в 1С с 2008 года, но пользуюсь не гуидами, а текущей датой в формате ГГГГММДДММСС: "[201303141439]"А теперь, предположим, у клиента старая программа и он вам присылает лог программы, а в новом коде уже и таких файлов нет, а может строки уже хорошо сместились. Я для себя сделал простейший генератор гуидов и растыкиваю по коду именно эти гуиды + сообщение (опционально). Гуиды позволяют почти со 100% точностью найти нужный кусок кода куда бы он не переместился. написал скриптик на VBS, который вызываю прямо в редакторе: Код: function glFrmDateTime( psDate ) Название: Re: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: Авварон от Июль 08, 2013, 22:13 Жесть какая, гуиды в коде...
Касательно стек трейса - я в свое время писал класс исключения, который умеет получать текущий стектрейс. В никсах работает даже в релизе (если апп не стрипнутый), а вот в винде - нет. Но, если поиграться с внешней отладочной инфой символами, может и можно что-то придумать. Название: Re: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: serg_hd от Июль 17, 2013, 16:38 https://code.google.com/p/google-breakpad/wiki/GettingStartedWithBreakpad
при падении вашей проги выдаст всё что надо знать об ошибке Название: Re: Qt & C++ :: Обработка ошибок и отладка сложных проектов Отправлено: kambala от Июль 17, 2013, 17:47 интересная штука, спасибо
|