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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Глобальный обработчик исключений  (Прочитано 10129 раз)
mejuhafr
Гость
« : Август 15, 2011, 14:17 »

Есть ли аналог TApplication.OnException ?
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #1 : Август 15, 2011, 15:41 »

заверни содержимое main() в try-catch
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
mejuhafr
Гость
« Ответ #2 : Август 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();
}
Не ловит ни то, ни то.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #3 : Август 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();
}
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
mejuhafr
Гость
« Ответ #4 : Август 15, 2011, 16:23 »

Вообще не проверятель? Веселый
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #5 : Август 15, 2011, 16:34 »

и правильно не ловит
Записан
brankovic
Гость
« Ответ #6 : Август 15, 2011, 16:52 »

и правильно не ловит

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

mejuhafr офтоп, но всё же: надо делать throw std::exception (), без new
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #7 : Август 15, 2011, 16:58 »

Вообще не проверятель? Веселый
см. скриншот
Код
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
из-за утечки памяти?
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #8 : Август 15, 2011, 16:59 »

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

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #9 : Август 15, 2011, 17:30 »

kambala, если исключения не будет, то ваш код уничтожит окно до того, как мы попадём в обработчик событий, что несколько неправильно. Да и исключение не из конструктора/show/setVisible() он не поймает.

Цитата: Авварон
Посему внутрях сигнал/слотов, в тч в цикле обработки событий (если мне не изменяет память) стоит try {} catch {}, к-ый ловит все эксепшны из слотов и "гасит" их; возможно что-то печатает в консоль/вызывает подменяемый хэндлер
Попробовал, у меня exception'ы, порождаемые в слотах никем не гасятся. Программа просто умирает.
Записан
brankovic
Гость
« Ответ #10 : Август 15, 2011, 17:56 »

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

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

Сообщений: 3258


Просмотр профиля
« Ответ #11 : Август 15, 2011, 17:59 »

Попробовал, у меня exception'ы, порождаемые в слотах никем не гасятся. Программа просто умирает.
А вы только директ соединение пробовали? Я процентов на 80 уверен, что в эвент лупе стоят QT_TRY
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #12 : Август 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.

Программа неожиданно завершилась.
« Последнее редактирование: Август 15, 2011, 18:13 от kambala » Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Akon
Гость
« Ответ #13 : Август 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, поскольку формально порядок вызова слотов не определен, а, следовательно, слоты несут независимый друг от друга код.

Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #14 : Август 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» значит лишь постановку в очередь.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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