exceptions abfangen

Alles rund um die Programmierung mit Qt
siemphil
Beiträge: 7
Registriert: 15. September 2006 14:51
Wohnort: München

exceptions abfangen

Beitrag von siemphil »

Hallo,
im folgenden Code wird eine Exception geworfen aber nicht vom catch in der main() abgefangen. Warum?

Code: Alles auswählen

//main.cpp
#include "Receiver.h"
#include <QApplication>
#include <QTimer>
#include <iostream>

int main(int argc, char* argv[]) {
  try {
      QApplication app(argc, argv);
      Receiver r;
      QTimer::singleShot(10, &r, SLOT(func()));
      app.exec();
  } catch(const std::string& msg) {
      std::cout << "catched: " << msg << std::endl;
  }
  return 0;
}

//Receiver.h
#include <QObject>

class Receiver : public QObject {
  Q_OBJECT
      public slots :
      void func() { throw std::string("Receiver"); }
};
Ich glaube nicht, dass der Code falsch ist. Liegt es vielleicht an meinen Einstellungen? Bitteschön:

gcc: 4.1.2
machine: i586-suse-linux
Qt: 4.2.2
Qt-configure: -debug-and-release -shared -no-qt3support -confirm-license -exceptions

mein .pro file:

Code: Alles auswählen

TEMPLATE = app
TARGET = 
DEPENDPATH += .
INCLUDEPATH += .
CONFIG += exceptions

# Input
HEADERS += Receiver.h
SOURCES += main.cpp
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Du versucht ein 'const &std::string' zu catchen, throwst aber 'nur' einen 'std::string'
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
siemphil
Beiträge: 7
Registriert: 15. September 2006 14:51
Wohnort: München

Beitrag von siemphil »

Christian81 hat geschrieben:Du versucht ein 'const &std::string' zu catchen, throwst aber 'nur' einen 'std::string'
Das hat mich jetzt verunsichert. Ich dachte das kann man machen. Trotzdem habe ich es nocheinmal getestet und mein 'catch' geändert:

Code: Alles auswählen

//...
catch(std::string msg)
//...
jetzt sind 'throw' und 'catch' quasi identisch. Das Abfangen funktioniert trotzdem noch nicht.
Übrigens ruft das 'throw' folgende Ausgabe hervor:

Code: Alles auswählen

terminate called after throwing an instance of 'std::string'
Abgebrochen
Das kommt scheinbar von Qt. Wird ein throw innerhalb eines Slots von einer Qt Funktion abgefangen und nicht weitergeworfen? Warum? Wie ist das richtige Vorgehen?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Das geht so nicht - wusste ich aber auch nicht...
Ich bekomme als Fehlermeldung immer
"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."
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
siemphil
Beiträge: 7
Registriert: 15. September 2006 14:51
Wohnort: München

Beitrag von siemphil »

Das ist die Lösung: QApplication::notify() re-implementieren. Komisch nur, dass "mein" Qt nicht so eine schöne Meldung macht.

Danke!
kitov
Beiträge: 36
Registriert: 29. November 2006 12:24

Beitrag von kitov »

Christian81 hat geschrieben:Du versucht ein 'const &std::string' zu catchen, throwst aber 'nur' einen 'std::string'
Das spielt doch keine Rolle .
Mit & sagst du bloss - keine Kopie machen , Referenz übergeben .
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Es geht mir nicht um die Referenz sondern eher um das const. Ich hatte schon des öfteren Probleme damit wenn der Typ von throw und catch nicht hundertprozentig übereinstimmte (msvc 7.1) und war sehr überrascht als der Codeschnipsel von siemphil mit msvc8 funktionierte (wenn man statt dem single shot einfach die Funktion aufruft die den throw erzeugt). Muss es wohl nochmal mit msvc 7.1 testen...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
siemphil
Beiträge: 7
Registriert: 15. September 2006 14:51
Wohnort: München

Beitrag von siemphil »

In Bezug auf das eigentliche Problem, welches ich in diesem Thread angesprochen habe, ist der korrekte Typ des geworfenen Objektes eigentlich egal. Im schlimmsten Fall wird es halt von catch(...) gefangen.

Das Problem war ja, dass das try/catch Konstrukt in main() nicht greift, wenn eine Exception aus der Eventloop von Qt heraus geworfen wird. Qt scheint selbst alles abzufangen und dann ein 'terminate' aufzurufen.

Zum 'catch(const std::string&)' : Ich habe es noch mal genau getestet. 'catch(const std::string&)' und 'throw std::string' abeiten tatellos.
Wenn 'throw' ein std::string ohne const wirft, ist das meiner Meinung nach durchaus mit 'const std::string&' kompatibel. Ich bin mir über denn Sinn der Referenz nicht klar, aber das const sollte keine Probleme machen.
gerome69
Beiträge: 188
Registriert: 28. April 2006 22:50
Wohnort: Berlin
Kontaktdaten:

Beitrag von gerome69 »

Schlage mich auch gerade mit dem Problem herum unter Win32.
Im .pro-File
ein CONFIG+=exceptions
Die Compileraufrufe auf der Konsole enthalten auch eindeutig ein "-fexceptions"

Aber folgendes Programm wird beendet mit einer MessageBox und "unknown software exception", statt meine Exception schön abzufangen:

Code: Alles auswählen

int main(int argc, char *argv[]) {
    printf("EXCEPTION-TEST-START\n");
       try {
           int z2=4-4;
           int z1=4/z2;
           printf("%d\n",z1);
       } catch (...) {printf("EXCEPTION\n");}
}  
Muß ich was spezielles includen?

Danke für Tips, Bernd
Massimo B.
Beiträge: 45
Registriert: 14. Juni 2006 11:05
Wohnort: Bonn, Germany

Kann fremde Exception unter Qt nicht auffangen

Beitrag von Massimo B. »

  • Hallo.
Mein Problem ist auch, dass ich die Exception nicht auffangen kann. Es wird eine Exception geworfen einer fremden Klasse aus dem Projekt GPSTk. Ich habe versucht das Beispiel so minimal wie möglich zu halten.
Das werfen einer einfachen Exception throw int(1) funktioniert. Ebenso funktioniert das Werfen der speziellen Exception GeometryException (API doc) in einem testcase ohne Qt. Mit Problem beendet das Programm aber mit:
  • terminate called after throwing an instance of 'gpstk::GeometryException'
Das Problem scheint also bei Qt in Verbindung mit GPSTk zu liegen, weshalb ich das Beispiel auch mit dieser speziellen Bibliothek angeben muss.

src.pro

Code: Alles auswählen

CONFIG += warn_on \
                  thread \
                  qt \
                  debug \
                  exceptions
LIBS += -lgpstk
  • Beispiel
  • main.cpp

    Code: Alles auswählen

    #include <QObject>
    #include <QApplication>
    #include <QPushButton>
    #include "test.h"
    int main(int argc, char *argv[])
    {
            QApplication a(argc, argv);
            QPushButton button("Elevation");
            Test t;
            button.show();
            QObject::connect(&button, SIGNAL(clicked()), &t, SLOT(test()));
            return a.exec();
    }
    test.h

    Code: Alles auswählen

    #include <QObject>
    class Test : public QObject {
            Q_OBJECT
            public slots:
                    void test();
    };
    test.cpp

    Code: Alles auswählen

    #include "test.h"
    #include <iostream>
    #include <Triple.hpp>
    #include <Position.hpp>
    #include <WGS84Geoid.hpp>
    void Test::test()
    {
        gpstk::WGS84Geoid* geoidP = new (gpstk::WGS84Geoid);
        gpstk::Position station,target;
        station.setGeodetic(0,0,0,geoidP);
        target.setGeodetic(0,0,0,geoidP);
        try {
    //         throw int(1);             /* funktioniert */
            std::cout << "Elevation: " 
                    << station.elevation(target) 
                    << std::endl;
        }
        catch(const int i) { qDebug("Exception int!"); }
        catch(gpstk::GeometryException e) {
            std::cerr << "Exception: " 
                    << e 
                    << std::endl;
        }
        catch(...) { std::cout << "Any Exception!"
                    << std::endl;
        }
    }
Gentoo (x86,ppc), KDevelop, Qt3, Qt4
Massimo B.
Beiträge: 45
Registriert: 14. Juni 2006 11:05
Wohnort: Bonn, Germany

Beitrag von Massimo B. »

Ich habe nun gelesen, dass dies ein allgemeines Design-Problem ist, da die meisten Bibliotheken wie STL nicht thread safe seien, während Qt multithreaded sei.
Ich habe den Vorschlag gelesen QApplication::notify() zu überschreiben. Kann das die Lösung sein, und wie sollte das aussehen?
Gentoo (x86,ppc), KDevelop, Qt3, Qt4
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Christian81 hat geschrieben:Das geht so nicht - wusste ich aber auch nicht...
[...]
You must reimplement QApplication::notify() and catch all exceptions there."
Das ist abhaengig davon, wie Qt (.. nicht dein Programm) compiliert wurde... aus mehreren Gruenden (compiler-support, performance) kann man Qt mit oder ohne Exceptions compilieren und ohne ergibt bei einer Exception waehrend eines Events diese Fehlermeldung.
Christian81 hat geschrieben:Es geht mir nicht um die Referenz sondern eher um das const. Ich hatte schon des öfteren Probleme damit wenn der Typ von throw und catch nicht hundertprozentig übereinstimmte (msvc 7.1) [..]
Naja, muss nicht einfach nur die Zuweisung moeglich sein? IMHO duerfte man also ein std::string einer const-referenz zuweisen, nicht aber ein const std::string einer (nicht-const) std::string-referenz..

gerome69 hat geschrieben:[...]
Muß ich was spezielles includen?
Danke für Tips, Bernd
du wirfst da ja auch keine Exception.. DbZ kann weder von Qt noch von C++ abgefangen werden.. dein Betriebsystem versucht dir mitzuteilen, dass dein Programm ganz böse dinge macht..
paoleela hat geschrieben:Ich habe nun gelesen, dass dies ein allgemeines Design-Problem ist, da die meisten Bibliotheken wie STL nicht thread safe seien, während Qt multithreaded sei.
Ich habe den Vorschlag gelesen QApplication::notify() zu überschreiben. Kann das die Lösung sein, und wie sollte das aussehen?
ein Standard-Qt-Programm ist Single-Thread.. -> hat also IMHO nichts damit zu tun..
gerome69
Beiträge: 188
Registriert: 28. April 2006 22:50
Wohnort: Berlin
Kontaktdaten:

Beitrag von gerome69 »

solarix hat geschrieben:
gerome69 hat geschrieben:[...]
Muß ich was spezielles includen?
Danke für Tips, Bernd
du wirfst da ja auch keine Exception.. DbZ kann weder von Qt noch von C++ abgefangen werden.. dein Betriebsystem versucht dir mitzuteilen, dass dein Programm ganz böse dinge macht..
Naja, nochmal zum Verständnis:

Code: Alles auswählen

int main(int argc, char *argv[]) {
    printf("EXCEPTION-TEST-START\n");
       try {
           int z2=4-4;
           int z1=4/z2;
           printf("%d\n",z1);
       } catch (...) {printf("EXCEPTION\n");}
}
Klar werfe ich nicht selbstständig eine exception dieser Art:

Code: Alles auswählen

if (z2==0) throw QString("Teilen durch 0 nicht erlaubt!");
Aber meine Vorstellung war bisher:
Wenn ich etwas in einen try-Block einfüge und ein catch(...) habe, wird jede Exception (in meinem konkreten Fall ein absichtlich herbeigeführtes Teilen durch 0) von dem catch(...) abgefangen und kann dort weiterbearbeitet werden, ohne dass mir das ganze Programm abstürzt.

Scheint aber wohl falsch zu sein, diese Vorstellung?!
Massimo B.
Beiträge: 45
Registriert: 14. Juni 2006 11:05
Wohnort: Bonn, Germany

Beitrag von Massimo B. »

solarix hat geschrieben:ein Standard-Qt-Programm ist Single-Thread.. -> hat also IMHO nichts damit zu tun..
Auf #qt sagte man mir, solange kein Qt-Code involviert ist (der evtl. nicht Exceptionfähig ist), sollte es keine Probleme geben. Bei meinem try/catch kommt eigentlich kein Qt-Code dazwischen.
Gentoo (x86,ppc), KDevelop, Qt3, Qt4
Zandru
Beiträge: 84
Registriert: 29. Mai 2007 15:35

Beitrag von Zandru »

das Problem ist, dass die Qt die Exception catched, *bevor* du die chance dazu hast. Natürlich wäre das im Single-Threaded Fall unnötig. Vielleicht kann man das irgendwie abschalten? QT_NO_EXCEPTIONS oder so? :)
Antworten