Russian Qt Forum

Qt => Вопросы новичков => Тема начата: mejuhafr от Августа 15, 2011, 14:17



Название: Глобальный обработчик исключений
Отправлено: mejuhafr от Августа 15, 2011, 14:17
Есть ли аналог TApplication.OnException ?


Название: Re: Глобальный обработчик исключений
Отправлено: kambala от Августа 15, 2011, 15:41
заверни содержимое main() в try-catch


Название: Re: Глобальный обработчик исключений
Отправлено: mejuhafr от Августа 15, 2011, 15:57
Чукча не читатель проверятель, чукча писатель?
Код
C++ (Qt)
#include <QtGui/QApplication>
#include "mainwindow.h"
 
int main(int argc, char *argv[])
{
   try
   {
       QApplication a(argc, argv);
       MainWindow w;
       w.show();
       return a.exec();
   }
   catch ( ... )
   {
       qDebug( "Eception" );
   }
}

Код
C++ (Qt)
void MainWindow::on_b1_clicked()
{
   int i=0;
   setWindowTitle(QString::number(1/i));
}
 
void MainWindow::on_b2_clicked()
{
   throw new std::exception();
}
Не ловит ни то, ни то.


Название: Re: Глобальный обработчик исключений
Отправлено: kambala от Августа 15, 2011, 16:10
видимо надо было уточнить:
Код
C++ (Qt)
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   try
   {
       MainWindow w;
       w.show();
   }
   catch ( ... )
   {
       qDebug( "Exception" );
   }
   return a.exec();
}


Название: Re: Глобальный обработчик исключений
Отправлено: mejuhafr от Августа 15, 2011, 16:23
Вообще не проверятель? :D


Название: Re: Глобальный обработчик исключений
Отправлено: Авварон от Августа 15, 2011, 16:34
и правильно не ловит


Название: Re: Глобальный обработчик исключений
Отправлено: brankovic от Августа 15, 2011, 16:52
и правильно не ловит

непонятно, можете пояснить? (первый пример c catch ( ... ))

mejuhafr офтоп, но всё же: надо делать throw std::exception (), без new


Название: Re: Глобальный обработчик исключений
Отправлено: kambala от Августа 15, 2011, 16:58
Вообще не проверятель? :D
см. скриншот
Код
C++ (Qt)
#include <QtGui/QApplication>
#include <QtGui/QWidget>
 
class Widget : public QWidget
{
   Q_OBJECT
 
public:
   Widget(QWidget *parent = 0) { throw std::exception(); }
};
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   try
   {
       Widget w;
       w.show();
   }
   catch (...)
   {
       qDebug("exception");
   }
 
   return a.exec();
}

mejuhafr офтоп, но всё же: надо делать throw std::exception (), без new
из-за утечки памяти?


Название: Re: Глобальный обработчик исключений
Отправлено: Авварон от Августа 15, 2011, 16:59
То есть вы считаете правильным, что эксепшн, брошенный в слоте, должен приходить в место вызова сигнала и сворачивать там стек (и 99% там не будет кода, к-ый бы их отлавливал и корректно очищал ресурсы - например такого вида char * buffer = new char[1024])
Посему внутрях сигнал/слотов, в тч в цикле обработки событий (если мне не изменяет память) стоит try {} catch {}, к-ый ловит все эксепшны из слотов и "гасит" их; возможно что-то печатает в консоль/вызывает подменяемый хэндлер


Название: Re: Глобальный обработчик исключений
Отправлено: LisandreL от Августа 15, 2011, 17:30
kambala, если исключения не будет, то ваш код уничтожит окно до того, как мы попадём в обработчик событий, что несколько неправильно. Да и исключение не из конструктора/show/setVisible() он не поймает.

Цитата: Авварон
Посему внутрях сигнал/слотов, в тч в цикле обработки событий (если мне не изменяет память) стоит try {} catch {}, к-ый ловит все эксепшны из слотов и "гасит" их; возможно что-то печатает в консоль/вызывает подменяемый хэндлер
Попробовал, у меня exception'ы, порождаемые в слотах никем не гасятся. Программа просто умирает.


Название: Re: Глобальный обработчик исключений
Отправлено: brankovic от Августа 15, 2011, 17:56
надо делать throw std::exception (), без new
из-за утечки памяти?

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


Название: Re: Глобальный обработчик исключений
Отправлено: Авварон от Августа 15, 2011, 17:59
Попробовал, у меня exception'ы, порождаемые в слотах никем не гасятся. Программа просто умирает.
А вы только директ соединение пробовали? Я процентов на 80 уверен, что в эвент лупе стоят QT_TRY


Название: Re: Глобальный обработчик исключений
Отправлено: kambala от Августа 15, 2011, 18:07
kambala, если исключения не будет, то ваш код уничтожит окно до того, как мы попадём в обработчик событий, что несколько неправильно. Да и исключение не из конструктора/show/setVisible() он не поймает.
да, точно, спасибо. чуть переделал:
Код
C++ (Qt)
#include <QtGui/QApplication>
#include <QtGui/QWidget>
#include <QtGui/QPushButton>
 
class Widget : public QWidget
{
   Q_OBJECT
 
public:
   Widget(QWidget *parent = 0)
   {
       QPushButton *b = new QPushButton("exception", this);
       connect(b, SIGNAL(clicked()), SLOT(throwException()));
   }
 
private slots:
   void throwException() { throw std::exception(); }
};
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   Widget w;
   try
   {
       w.show();
   }
   catch (...)
   {
       qDebug("exception");
   }
 
   return a.exec();
}
и тут же получил "ответ" в консоли:
Цитировать
Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt. You must
reimplement QApplication::notify() and catch all exceptions there.

Программа неожиданно завершилась.


Название: Re: Глобальный обработчик исключений
Отправлено: Akon от Августа 21, 2011, 20:38
Есть ли аналог TApplication.OnException ?

TApplication.OnException возникает при генерации исключения в цикле обработки сообщений. Заворачивание тела main() в try/catch к этому отношения не имеет.

Для перехвата исключений из цикла необходимо переопределить Q[Core]Application::notify().
Код:
class App : public QApplication
{
    Q_OBJECT
    typedef QApplication Base;

...

Q_SIGNALS:
    void onException(const std::exception& exception, bool& handled);

protected:
    virtual bool notify(QObject* receiver, QEvent* event)
    {
        try {
            return Base::notify(receiver, event);
        }
        catch (const std::exception& exception) {
            bool handled = false;
            Q_EMIT onException(exception, handled);
            if (!handled)
                QMessageBox::critical(0, QApplication::instance()->applicationName(),
                    exception.what(), QMessageBox::Ok, QMessageBox::NoButton);
        }
        catch (...) {
    QMessageBox::critical(0, QApplication::instance()->applicationName(),
        "Application general failure", QMessageBox::Ok, QMessageBox::NoButton);             
        }

        return false;
    }
};

Но все это не вяжется с дизайном Qt. Об ошибках здесь сообщается не через исключения.

Для того, чтобы ловить исключения из слотов необходимо патчить QMetaObject::activate(). В частности, будет возможен вызов второго и всех остальных приконнекченных к данному сигналу слотов, если первый слот выбросит исключение. Это согласуется с дизайном Qt, поскольку формально порядок вызова слотов не определен, а, следовательно, слоты несут независимый друг от друга код.



Название: Re: Глобальный обработчик исключений
Отправлено: LisandreL от Августа 21, 2011, 23:43
поскольку формально порядок вызова слотов не определен, а, следовательно, слоты несут независимый друг от друга код.
В последних версиях Qt эту неопределённость убрали и в справке порядок официально закрепили порядок (хотя, говорят, и раньше оно работало именно так):
Цитировать
If a signal is connected to several slots, the slots are activated in the same order as the order the connection was made, when the signal is emitted.
Хотя надо понимать, что в случае соединения через очередь «slot is activated» значит лишь постановку в очередь.


Название: Re: Глобальный обработчик исключений
Отправлено: Akon от Августа 22, 2011, 12:45
Раньше так и было, просто тролли оставляли себе свободу изменить порядок. Если порядок определен, то правомерен дизайн, полагающийся на то, что один слот будет вызван раньше другого. В этом случае с исключениями в слотах еще проблема - если первый слот выбрасывает исключение, то второму слоту, зависимому от первого, исключение тем или иным образом должно передаваться. В общем случае я бы не стал делать дизайн, полагающийся на определенный порядок вызова слотов.


Название: Re: Глобальный обработчик исключений
Отправлено: Danila_Bagrofff от Августа 23, 2011, 10:15
а скажите, сам кути генерирует эксепшены в случае, если происходит крах приложения из-за каких=либо проблем работы с памятью.

Вот надо отловить кутешные exeptionы. Что надо для этого. И как это сделать?... Никак не пойму логику кути в этом вопросе.

Свои можно генерить и обрабатывать. А кутешные?


Название: Re: Глобальный обработчик исключений
Отправлено: Авварон от Августа 23, 2011, 11:43
Да не генерит Qt  эксепшны, сколько раз повторять?


Название: Re: Глобальный обработчик исключений
Отправлено: brankovic от Августа 23, 2011, 11:51
Вы наверное имеете ввиду, что нарушение памяти должно приводить к исключению. Это не так, нарушение памяти отловить в общем случае невозможно.

Ещё, в Qt исключения не используются (дизайн такой), но если бы использовались, то были бы обычными C++ исключениями. "Необычные", в т.ч. и по поводу нарушений памяти умеет генерить ОС windows, но этим механизмом пользоваться нельзя.


Название: Re: Глобальный обработчик исключений
Отправлено: Авварон от Августа 23, 2011, 15:35
Тут где-то была библиотечка, выдранная из либжава, к-ая генерит арифметические эксепшны и эксепшны обращения к памяти