Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие _ Qt Exceptions

Автор: JuryS1806 2.10.2010, 21:38

Здраствуйте, товарищи.

Столкнулся с такой проблемой. Сегодня установил Qt 4.7.0.

и теперь не могу отлавливать Exception'ы в main.
В общем это выглядит так:

Runagain:
            try
        {
                app.exec();
        }
                catch (...)
                  {
                    QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Неизвестная ошибка.</b>")+runagainMsg);
                    goto Runagain;
                  }
    return 0;

И до версии 4.6.3 это срабатывало, но теперь нет, при том что exception'ы отлавливаются в любых функциях и классах, но вот не в main. Просто наработал столько, что сейчас во всех классах и методах прописывать try -> catch . Да и не нужно. Только вот бывают критические ошибки и хотелось бы их отловить в main.

Спасибо за помощь !

Автор: Авварон 2.10.2010, 23:05

Мне казалось, что эксепшны ловятся в цикле событий и там и помирают.

Автор: JuryS1806 2.10.2010, 23:10

Цитата(Авварон @ 3.10.2010, 0:05) *
Мне казалось, что эксепшны ловятся в цикле событий и там и помирают.

Они генерируются где угодно и потом начинают передаваться выше, до тех пор пока кто-нибудь их не отработает. К примеру, я даже в вызове какого-то класса заколочу try и как результат, в случае возникновения ошибки поймаю его.

Вещь конечно тормознутая, но незаменимая.

Я сейчас пересобрал проект с ключом DEFINES += No_Exception.

Не знаю как. но Qt его съел и теперь программа вылетает, также игнорирует catch (...) в функции main(), но теперь сам Qt ничего не пишет, просто мол приложение завершено с кодом 0. И при этом exception'ы функций работают исправно.

Все это подозрительно очень. Я думаю это баг QApplication.

Автор: Алексей1153 3.10.2010, 6:39

[offtop]
JuryS1806, goto - зло! А если уж используешь, пользуйся правильно

Runagain:
       try
       {
               app.exec();
       }
       catch (...)
       {
           QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Неизвестная ошибка.</b>")+runagainMsg);
        }

   goto Runagain;
   return 0;


[/offtop]

Автор: JuryS1806 3.10.2010, 9:55

Да хоть бы QMessageBox отработал, а то вылет и все тут. Я кстати говоря 4.6.0, 4.6.2, 4.6.3 перепробовал и везде одно и то же. И при том что судя по всему проблема не в Qt а в Linux. Под Windows это срабатывает изумительно. А под ubuntu нет.
Вот и не пойму в чем дело...

Автор: kuzulis 4.10.2010, 14:24

А под Linux эксепшены не канают. Забудьте про них вообще.

Автор: kwisp 4.10.2010, 14:42

Цитата(kuzulis @ 4.10.2010, 15:24) *
А под Linux эксепшены не канают. Забудьте про них вообще.

???
а по подробнее можешь растолковать?

JuryS1806,
может исключения перехватываются до main() и в отсутствии корректной реакции вызывают крах программы.

Автор: kuzulis 4.10.2010, 15:12

Цитата
???
а по подробнее можешь растолковать?

Да я в подробности не вдавался, но по слухам в Linux лучше проверять возвращаемые значения.
Да и везде где я видел код для Linux, я нигде (или оч редко) видел обработку исключений..

А вообще, почитать тут можно кое что (примерчик): http://www.visualdata.ru/blog/109-segv-signal.html

Автор: kwisp 4.10.2010, 15:19

Цитата(kuzulis @ 4.10.2010, 16:12) *
Да я в подробности не вдавался, но по слухам в Linux лучше проверять возвращаемые значения.

ну товарищ это не серьезно. :(
если ты сам генерируешь способ сообщения об ошибке, мало кому интересно как это у тебя будет возвращаемое значение или исключение. однако есть стандартные средства(stl к примеру), которые уже генерируют исключения и обрабатывать их надо.
чем таким принципиальным функция линукс версия std::vector<Type>::at(int) отличается от виндовой версии?
и там и там будет исключение std::out_of_range в случае выхода за пределы вектора.

как собираешься сообщить об ошибке в конструкторе через возвращаемое значение?

П.С.
в статье нет ни слова про возвращаемые значения в случае ошибок.
ключевая мысль статьи
Цитата
В данном примере рассмотрен вариант трансляции системных сигналов SIGSEGV и SIGFPE в стандартные исключения языка c++ для i386/gcc/linux.


Автор: kuzulis 4.10.2010, 15:27

Цитата
как собираешься сообщить об ошибке в конструкторе через возвращаемое значение?

Хм.. Похожая тема и на prog.org.ru была. И там были примеры с исключениями в этом случае (и даже я тему создавал там такую) :)

Но я бы проверил бы величину значения int и выставил бы в конструкторе какой-то флаг типа bool valid = false или еще как... И уже далее перед выполнением каких нибудь методов (тот.же .at(int)), я бы делал проверку на этот флаг и , соответственно, дальше уже бы решал что делать.
--
т.е. у меня "парадигма" - всегда контролровать свои переменные принаписании кода, а не полагаться на исключения.

ЗЫ:
нашел тему: http://www.prog.org.ru/topic_13051_0.html

Автор: kwisp 4.10.2010, 15:34

Цитата(kuzulis @ 4.10.2010, 16:27) *
Но я бы проверил бы величину значения int и выставил бы в конструкторе какой-то флаг типа bool valid = false или еще как... И уже далее перед выполнением каких нибудь методов (тот.же .at(int)), я бы делал проверку на этот флаг и , соответственно, дальше уже бы решал что делать.

мда. ничего не скажешь. можно только удачи пожелать :) без обид...
никак не пойму почему:
Цитата(kuzulis @ 4.10.2010, 15:24) *
А под Linux эксепшены не канают. Забудьте про них вообще.

из чего это следует?

Цитата(kwisp @ 4.10.2010, 16:33) *
всегда контролировать свои переменные при написании кода, а не полагаться на исключения.

согласен целиком и полностью, полагаться на них не стоит.
но они уже есть и о них в линуксе надо помнить.

Автор: kuzulis 4.10.2010, 15:41

Цитата
из чего это следует?

Да это просто вброс в стиле ЛОР-а :)
который не несет никакой информации в принципе. Это субъективное мое личное мнение на данный момент.

Автор: kwisp 4.10.2010, 15:48

Цитата(kuzulis @ 4.10.2010, 16:41) *
Да это просто вброс в стиле ЛОР-а :)

ну спасибо! :)
к чему катимся, товарищи?
давай договоримся не писать подобных ЛОР-сообщений.

П.С.
за ссылку спасибо, оч. интересно, как раз вплотную с этой проблемой столкнулся.
даешь разумную обработку ошибок!

Автор: JuryS1806 14.10.2010, 2:20

Спасибо за Ваше активное участие в теме !

К сожалению, без эксцепшенов не обойтись и никакие тут int значения не помогут.
Вот например я сейчас разбросал программу на 87 библиотек, каждая ~ весит по 2 Мб, половина из них OpenCascade.
Так вот, чтобы передать int например из Foundation и проследить до самого верха, при этом одни и те же функции вызываются из разных классов и т.д. и т.п...

Вообще, в Windows отрабатываются exception'ы и в main, в Linux везде, кроме main. Почему не знаю, но оставил и там и + добавил exception'ы везде где можно...

А в общем код следующий:

Раскрывающийся текст

#include <QApplication>
#include "mainwindow.h"
#include "ExceptionHead.h"

//void loadModules(QSplashScreen*) { } ;

int main (int argc, char** argv)
{
QApplication app(argc, argv);
/* QSplashScreen splash(QPixmap(":/Visual3D/Splash/Resurs/Load.png"));
splash.show();
Q_INIT_RESOURCE(Visual3D);
QLabel lbl("<H1><CENTER>Ready!</CENTER></H1>");
loadModules(&splash);
splash.finish(&lbl);
*/
//QDir::setCurrent(QCoreApplication::applicationDirPath());

QString resdir;
QString translatorPath;

#ifdef WNT //Настройки для Windows

const QString initdir = QCoreApplication::applicationDirPath();
resdir = initdir + "/src/Resource";
translatorPath = initdir+"/src/messages/Ru_ru.qm";

#else //Настройки для Linux

resdir = "/opt/Visual3D/bin/src/Resource";
translatorPath = "/opt/Visual3D/bin/src/messages/Ru_ru.qm";

#endif

qputenv("CSF_ResourcesDefaults",resdir.toAscii());
qputenv("CSF_PluginDefaults",resdir.toAscii());

QTranslator* translator = new QTranslator; // создаем переводчик
translator->load(translatorPath); // загрузка файла qt_*.qm*
app.installTranslator(translator); // устанока переводчика

MainWindow* w = new MainWindow();
w->setWindowTitle(QString::fromUtf8("Графический редактор"));
w->setWindowIcon(QPixmap(":/Visual3D/icons/Resurs/MainWindow.png"));
QString myArgument = argv[1];

if (myArgument.isEmpty())
w->Init();
w->showMaximized();

if (!myArgument.isEmpty())
{
if (!w->InitArguments(argv[1])) //Здесь будут открываться файлы и если будет исполнен макрос и он будет завершен
//командой quit(), тогда будет установлено свойство MainWindow -> disable
//и соответственно Exception'ы не будут отрабатываться.
//Также exception'ы не будут отрабатываться при автозапуске макроса.
{
w->Init();
w->showMaximized();
}
}

if (w->isEnabled())
{
QString msgHead = QString::fromUtf8("Критическая ошибка");
QString runagainMsg = QString::fromUtf8(" В процессе работы возникла критическая ошибка. "
"Сейчас будет предпринята попытка восстановить "
"рабочее состояние программы. "
"В случае неудачи рабочие файлы будут автоматически "
"открыты при следующем запуске программы.");
Runagain:
try
{
app.exec();
}

catch (Standard_AbortiveTransaction)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 1. Прерванная транзакция.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_ConstructionError)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 2. Ошибка построения.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_DimensionMismatch)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 3. Несоответствие измерения.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_DimensionError)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 4. Ошибка измерения.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_DivideByZero)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 5. Деление на ноль.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_NullObject)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 6. Нулевой объект.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_ImmutableObject)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 7. Неизменный Объект.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_MultiplyDefined)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 8. Повторный заголовок.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_NegativeValue)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 9. Отрицательная величина.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_NoMoreObject)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 10. Больше нет объектов.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_NoSuchObject)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 11. Нет такого объекта.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_NullValue)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 12. Нулевое значение.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_OutOfRange)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 13. Вне диапазона.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_RangeError)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 14. Ошибка диапазона.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_TypeMismatch)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 15. Несоответствие типов.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_DomainError)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 16. Ошибка области.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_NotImplemented)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 17. Невозможно осуществить.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_Overflow)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 18. Перегрузка.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_Underflow)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 19. Недогрузка.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_NumericError)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 20. Числовая ошибка.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_OutOfMemory)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 21. Нехватает памяти.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_ProgramError)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 22. Ошибка программы.</b>")+runagainMsg);
goto Runagain;
}

catch (Standard_TooManyUsers)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 23. Слишком много пользователей.</b>")+runagainMsg);
goto Runagain;
}

catch (...)
{
QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Неизвестная ошибка.</b>")+runagainMsg);
goto Runagain;
}
}
return 0;
}



и теперь все эти exception'ы распихал по программе... Тестирую, ищу где мог пропустить....

Автор: Алексей1153 14.10.2010, 6:38

JuryS1806, так и выходишь из catch при помощи goto - потом не удивляйся неожиданным сюрпризам ))

вот кусок кода с try , без goto


Раскрывающийся текст

while(1)
{
    try
    {
        app.exec();
        break;
    }

    catch (Standard_AbortiveTransaction)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 1. Прерванная транзакция.</b>")+runagainMsg);
    }

    catch (Standard_ConstructionError)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 2. Ошибка построения.</b>")+runagainMsg);
    }

    catch (Standard_DimensionMismatch)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 3. Несоответствие измерения.</b>")+runagainMsg);
    }

    catch (Standard_DimensionError)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 4. Ошибка измерения.</b>")+runagainMsg);
    }

    catch (Standard_DivideByZero)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 5. Деление на ноль.</b>")+runagainMsg);
    }

    catch (Standard_NullObject)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 6. Нулевой объект.</b>")+runagainMsg);
    }

    catch (Standard_ImmutableObject)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 7. Неизменный Объект.</b>")+runagainMsg);
    }

    catch (Standard_MultiplyDefined)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 8. Повторный заголовок.</b>")+runagainMsg);
    }

    catch (Standard_NegativeValue)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 9. Отрицательная величина.</b>")+runagainMsg);
    }

    catch (Standard_NoMoreObject)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 10. Больше нет объектов.</b>")+runagainMsg);
    }

    catch (Standard_NoSuchObject)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 11. Нет такого объекта.</b>")+runagainMsg);
    }

    catch (Standard_NullValue)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 12. Нулевое значение.</b>")+runagainMsg);
    }

    catch (Standard_OutOfRange)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 13. Вне диапазона.</b>")+runagainMsg);
    }

    catch (Standard_RangeError)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 14. Ошибка диапазона.</b>")+runagainMsg);
    }

    catch (Standard_TypeMismatch)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 15. Несоответствие типов.</b>")+runagainMsg);
    }

    catch (Standard_DomainError)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 16. Ошибка области.</b>")+runagainMsg);
    }

    catch (Standard_NotImplemented)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 17. Невозможно осуществить.</b>")+runagainMsg);
    }

    catch (Standard_Overflow)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 18. Перегрузка.</b>")+runagainMsg);
    }

    catch (Standard_Underflow)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 19. Недогрузка.</b>")+runagainMsg);
    }

    catch (Standard_NumericError)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 20. Числовая ошибка.</b>")+runagainMsg);
    }

    catch (Standard_OutOfMemory)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 21. Нехватает памяти.</b>")+runagainMsg);
    }

    catch (Standard_ProgramError)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 22. Ошибка программы.</b>")+runagainMsg);
    }

    catch (Standard_TooManyUsers)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Ошибка № 23. Слишком много пользователей.</b>")+runagainMsg);
    }

    catch (...)
    {
        QMessageBox::critical(0,msgHead,QString::fromUtf8("<b>Неизвестная ошибка.</b>")+runagainMsg);
    }
}



Автор: JuryS1806 15.10.2010, 0:46

Сейчас опробую !
Кстати, насчет необходимости exception'ов в принципе, а то раньше вопрос был типа нафиг они нужны и т.д.

Я тут долго с одной вещью боролся и только с месяц назад победил.
Приблизительно это выглядит так:

...
    StMaterialSel = new QComboBox;
    StMaterialSel->addItems(basemat->GetListOfMaterial());
    connect(StMaterialSel, SIGNAL(currentIndexChanged(int)),
            this, SLOT(setMyViewMaterial(int)));

    int myIndex = basemat->GetVirtualIndex(index_m);
....
ComboNotReady:
    try
    {
        StMaterialSel->setCurrentIndex(myIndex);
    }
    catch (...)
    {
        goto ComboNotReady;
    }
......


При том что Qt просто вылетал без всяких сообщений. Происходило это через раз... Например на двухядерных машинах 1/4, на P3 600 через раз.
Но страшно то что не знаешь, выпадет Qt или нет...

Так вот, думал что у меня руки кривые и пробовал по разному. В таком исполнении если в catch положить QMessageBox, то он будет кричать... и все работает. /не bool вызовы списка и индека, не processEvents здесь не помогали/

Еще в защиту exception'ов:

считаю они просто необходимы, тем более при длительной и большой разработке, учитывая сложность. Думаю что никакими int значения не отследить exception'ы при расчете например треугольников Серпинского и прочей ереси

...Приветствую всех желающих заняться философией в этом топике :)

Автор: Алексей1153 15.10.2010, 6:40

Цитата(JuryS1806 @ 15.10.2010, 3:46) *
Qt просто вылетал

наверное, не Qt, а программа ?

Цитата(JuryS1806 @ 15.10.2010, 3:46) *
Приветствую всех желающих заняться философией в этом топике

философия, значит, такая: на эксепшены не надеяться. Всегда создавать условия, когда эксепшена быть не должно. Не заходить в блок try в цикле - будут тормоза (правда, всё зависит от назначения и количества итераций цикла).
Большой цикл можно обернуть снаружи в try, если там, в принципе, может вылететь что-нибудь :)

Автор: JuryS1806 15.10.2010, 23:29

да уж

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)