exception handling in c++



  • Hi
    Ich wollte mir einmal exception handling in c++ anschauen.
    dazu hab ich mir eine exception klasse ( myexception ) von exception abgeleitet.

    wenn ich die allerdings werfe, dann bricht mein programm ab :(.
    also hab ich noch irgendwas nicht ganz richtig verstanden:

    #include<iostream>
    #include "MyException.h"
    
    using namespace std;
    
    class DBException : public myException 
    {
    public:
        DBException(const string& reason) : myException(reason) {}
    };
    
    void eingabe () throw (DBException*)
    {
    string s;
    cin >> s;
    throw DBException("bla");
    }
    
    int main (int argc, char **argv)
    {
    	try
    	{
    		eingabe();
    	}
    	catch (DBException* e)
    	{
    		cerr << (e->what()) << endl;
    	}
    
    	try
    	{
    		eingabe();
    	}
    	catch (DBException* e)
    	{
    		cerr << (e->what()) << endl;
    		exit(1);
    	}
    return 0;
    }
    

    wie man sieht rufe ich eingabe 2 mal auf.
    bei mir bricht das programm allerdings beim ersten cache block mit core dumped ab.

    was mach ich falsch ?

    danke
    Verucca



  • Naja, Du versuchst, einen Pointer zu fangen, wo Du ein Objekt wirfst ....
    Kann auch sein, dass Dein Programm bei der throw()-Spezifikation rausfliegt (hängt aber von Compiler und -einstellungen ab).

    Fang lieber Referenzen (das mit dem "Objekte werfen" ist schon gut so), das macht weniger Probleme.

    #include<iostream>
    #include "MyException.h"
    
    using namespace std;
    
    class DBException : public myException
    {
    public:
        DBException(const string& reason) : myException(reason) {}
    };
    
    void eingabe () throw (DBException)
    {
       string s;
       cin >> s;
       throw DBException("bla");
    }
    
    int main (int argc, char **argv)
    {
        try
        {
            eingabe();
        }
        catch (DBException& e)
        {
            cerr << e.what() << endl;
        }
    
        try
        {
            eingabe();
        }
        catch (DBException& e)
        {
            cerr << e.what() << endl;
            exit(1);
        }
       return 0;
    }
    

    Außerdem ist es keine schlechte Idee, seine exceptions von std::runtime_error und seinen Kindern abzuleiten (gibts per #incude <stdexcept> ).

    Ach ja: Die throw-Spezifikation wird nur zur Laufzeit überprüft (falls überhaupt) und führt dann zu einem abort() (sieht auch ein wenig wie ein "core dump" aus) ... ist also anders, als man das zu Anfang denkt. Ich persönlich nutze sie deswegen nicht mehr, weil sie mir zu wenig Gewinn und zuviel Aufhebens sind. (außer da, wo es natürlich sein muss wg. fremder API&Co)

    Gruß,

    Simon2.



  • Das Programm müsste eigentlich ganz normal via terminate beendet werden.

    Ändere deine catch-clauses in DBException& , und lass die Exception-Spezifikation am besten ganz weg.



  • lo
    naja die genaue meldung ist:

    terminate called after throwing an instance of 'DBException'
    what(): bla
    Aborted (core dumped)

    und ableiten tu ich das wie gesagt von exception:

    #ifndef MYEXCEPTION_H_
    #define MYEXCEPTION_H_
    #include<exception>
    #include<string>
    
    using namespace std;
    
    class myException : public exception {
    public:
        myException(const string& reason) : reason(reason) {}
        virtual ~myException() throw() {}
        virtual const char* what() const throw() 
        {
            return reason.c_str();
        }
    
    private:
        const string reason;
    }; 
    
    #endif /*MYEXCEPTION_H_*/
    

    jedenfalls macht es bei der meldung keinen unterschied ob ich referenz auf das objekt oder den pointer typ übergebe .... habs gerade ausprobiert.
    die Meldung bleibt die gleiche..

    lg
    Verucca



  • Hi,

    lass doch mal Deinen aktuellen Code sehen ...

    Folgender Code läuft bei mir (gcc 3.4.4) nämlich wie gewünscht:

    using namespace std;
    
    class myException : public exception {
    public:
        myException(const string& reason) : reason(reason) {}
        virtual ~myException() throw() {}
        virtual const char* what() const throw()
        {
            return reason.c_str();
        }
    
    private:
        const string reason;
    }; 
    
    class DBException : public myException
    {
    public:
        DBException(const string& reason) : myException(reason) {}
    };
    
    void eingabe () throw (DBException)
    {
       string s;
       cin >> s;
       throw DBException("bla");
    }
    
    int main (int argc, char **argv)
    {
        try
        {
            eingabe();
        }
        catch (DBException& e)
        {
            cerr << e.what() << endl;
        }
    
        try
        {
            eingabe();
        }
        catch (DBException& e)
        {
            cerr << e.what() << endl;
            exit(1);
        }
       return 0;
    }
    

    Gruß,

    Simon2.



  • Verucca schrieb:

    jedenfalls macht es bei der meldung keinen unterschied ob ich referenz auf das objekt oder den pointer typ übergebe .... habs gerade ausprobiert.
    die Meldung bleibt die gleiche..

    Das terminate kommt durch deine throw-specification - ändere die wie Simon2 es vorschlägt, oder lass sie besser noch ganz weg.



  • finix schrieb:

    ...oder lass sie besser noch ganz weg.

    Wie Simon2 es ebenfalls vorschlägt... 😉

    Gruß,

    Simon2.



  • hi
    ja betriebsblindheit würde ich sagen 🙂

    ich hab alle pointer entfernt nur beim throw nicht ......

    void eingabe () throw (DBException*)
    

    hier war immer noch der pointer drin .....

    funktioniert alles - naja wenigstens hab ich das alles so halbwegs richtig verstanden....

    danke war genau was ich gebraucht hab ....

    Aber um mein verständnis zu fördern.
    In allen beispielen die ich so im google gefunden hab hat niemand eine exception klasse abgeleitet.
    Im prinzip haben die immer nur eine einfache klasse mit der methode what() deffiniert aber nie vererbt.
    Warum stell ich mir hier die frage?

    lg
    Verucca



  • Hm, Unwissenheit? 😉
    Ich finde es generell gut, auch eigene Exceptions immer von std::exception (oder dessen Kinder runtime_error und logic_error) abzuleiten, da man dann die Standard-Exceptions zusammen mit den eigenen abfangen kann (indem man die gemeinsame Basis fängt), wenn es ungeeignet erscheint eine der konkreten Exceptions zu behandeln.



  • Verstehe na dann ists ja gut - wenn ich einmal was geschreiben hab mach ich sowieso nur noch copy und paste - deshalb will ich das immer vernüftig haben ...

    Wie man sieht tu ich mir in c++ aber immer noch mit den pointern ein bisschen schwer .... auch wenn ichs grundsätzlich verstehe finde ich es einfach immer noch ziemlich unübersichtlich - aber ich denke mal man gewöhnt sich daran ...
    lg
    Verucca


Anmelden zum Antworten