Errorcodes



  • Nexus schrieb:

    hartmut1164 schrieb:

    Das Betriebssystem sollte den Speicher wieder freigeben.

    Darauf sollte man sich nicht verlassen. Was aber auch kein Problem ist, wenn man sein Design mit RAII ein wenig durchdacht hat.

    Die Funktion exit() räumt den Stack beim Beenden normal auf - etwa im Gegensatz zu abort() . Wenn man sich in der main() -Funktion befindet, kann man gerade so gut return schreiben.

    abort () hat dabei noch eine andere Funktion, dass es einen Stacktrace erzeugt (z.B. als Core-File), den man fuer Debugzwecke benutzen kann.



  • return aus der main() ist schon ganz gut.

    aber wie kriegt man auf einer unterunterfunktion es hin, die main() was returnen zu lassen? mit exceptions!

    void bar(){
       //char* c=new char[3000000000];//main returnt 1
       throw FalschesPasswortException();//main returnt 3
       //throw SocketException();//main returnt 2
    }
    
    void foo(){
       bar();
    }
    
    int main(){
       try{
         foo();
         return 0;
       }
       catch(FalschesPasswortException &e){
          cout<<"Fataler Fehler: "<<"Falsches Passwort"<<'\n';
          return 3;
       }
       catch(std::exception& e){
          cout<<"Fataler Fehler: "<<e.why()<<'\n';
          return 1;
       }
       catch(...){
          cout<<"Fataler Fehler: "<<"unbekannter Fehler"<<'\n';
          return 2;
       }
    }
    


  • hartmut1164 schrieb:

    abort () hat dabei noch eine andere Funktion, dass es einen Stacktrace erzeugt (z.B. als Core-File), den man fuer Debugzwecke benutzen kann.

    Danke, das war mir nicht bekannt. Aber in fertigen Programmen sollte abort() eigentlich nicht vorkommen. Meistens schafft man es auch irgendwie einzurichten, dass man kein exit() benötigt...

    volkard schrieb:

    e.why()
    

    Eine philosophische Memberfunktion ist immer nützlich. 😃



  • Nexus schrieb:

    Die Funktion exit() räumt den Stack beim Beenden normal auf - etwa im Gegensatz zu abort() .

    stimmt doch gar nicht!

    #include <fstream>
    #include <cstdlib>
    using namespace std;
    
    int main()
    {
    	ofstream out("test.txt");
    	out<<"hallo\n";
    	exit(0);
    }
    

    mit exit ist danach dei datei leer. mit return klappts.


  • Administrator

    Ergänzung:

    Standard C++ 98
    3.6.1 Main function
    Abschnitt 4

    Calling the function
    void exit(int);
    declared in <cstdlib> (18.3) terminates the program without leaving the current block and hence without destroying any objects with automatic storage duration (12.4). If exit is called to end a program during the destruction of an object with static storage duration, the program has undefined behavior.

    Standard C++ 98
    3.6.3 Termination
    Abschnitt 4

    Calling the function
    void abort();
    declared in <cstdlib> terminates the program without executing destructors for objects of automatic or static storage duration and without calling the functions passed to atexit() .

    Grüssli



  • Nexus schrieb:

    hartmut1164 schrieb:

    abort () hat dabei noch eine andere Funktion, dass es einen Stacktrace erzeugt (z.B. als Core-File), den man fuer Debugzwecke benutzen kann.

    Danke, das war mir nicht bekannt. Aber in fertigen Programmen sollte abort() eigentlich nicht vorkommen.

    Ueberhaupt nicht - denke nur an die Verwendung von std::bad_alloc:

    int *aGanzGross = NULL;
    try
    {
       aGanzGross= new int [1000000];
    }
    catch (bad_alloc&)
    {
       cerr << "Autsch" << endl;
       abort ();
    }
    

    Das hat die gleiche Funktion wie in C:

    int   *aGanzGross;
    
    aGanzGross = calloc (1000000, sizeof (int));
    if (aGanzGross == NULL)
    {
        fprintf (stderr, "Autsch!\n");
        abort ();
    }
    


  • hartmut1164 schrieb:

    Ueberhaupt nicht - denke nur an die Verwendung von std::bad_alloc:

    nein, so läßt du die dateien offen, du schließt die datenbanken nicht und machst mit abort einfach alles falsch.
    wirf doch einfach hoch bis zu main und geh dort mit return raus.


  • Administrator

    Es wäre sogar erlaubt, die Exception ganz durchwerfen zu lassen, also sie nicht mal in der main zu fangen. Wäre immer noch besser als abort aufzurufen.

    Grüssli



  • Hmm. Da habe ich wohl den Satz auf www.cplusplus.com falsch interpretiert:

    exit schrieb:

    Terminates the process normally, performing the regular cleanup for terminating processes.

    Dravere schrieb:

    Es wäre sogar erlaubt, die Exception ganz durchwerfen zu lassen, also sie nicht mal in der main zu fangen. Wäre immer noch besser als abort aufzurufen.

    Führt das nicht zu Programmabstürzen? Soweit ich mich erinnern kann, haben ungefangene Exceptions in Release-Versionen immer zu Fehlermeldungen wie "Programm.exe funktioniert nicht mehr" geführt...



  • volkard schrieb:

    hartmut1164 schrieb:

    Ueberhaupt nicht - denke nur an die Verwendung von std::bad_alloc:

    nein, so läßt du die dateien offen, du schließt die datenbanken nicht und machst mit abort einfach alles falsch.
    wirf doch einfach hoch bis zu main und geh dort mit return raus.

    Mmmhh ... Jein. abort () ist soetwas wie das Zeichen fuer es "ging richtig und ganz boese schief". Wenn bei den heutigen Systemen kein Heap zu allocieren ist, dann lief etwas sehr uebel und es ist IMHO dann besser, die Sache so brutal als moeglich abzuwuergen. Eine Datenbank sollte mit einem toten Client zurechtkommen, und auch ein noch offener File ist fuer ein Betriebssystem heute kein wirkliches Problem mehr sein - schliesslich entspricht abort () etwa dem Verhalten von SIGKILL und damit muss das Betriebssystem/Datenbanken etc. auch umgehen koennen.



  • hartmut1164 schrieb:

    Wenn bei den heutigen Systemen kein Heap zu allocieren ist, dann lief etwas sehr uebel

    Wieso? std::bad_alloc wird zum Beispiel auch geworfen, wenn kein genügend grosser Speicherbereich an einem Stück gefunden werden kann.


  • Administrator

    hartmut1164 schrieb:

    Mmmhh ... Jein. abort () ist soetwas wie das Zeichen fuer es ging richtig schief. Wenn bei den heutigen Systemen kein Heap zu allocieren ist, dann lief etwas sehr uebel und es ist IMHO dann besser, die Sache so brutal als moeglich abzuwuergen. Eine Datenbank sollte mit einem toten Client zurechtkommen, und auch ein noch offener File ist fuer ein Betriebssystem heute kein wirkliches Problem mehr sein - schliesslich entspricht abort () etwa dem Verhalten von SIGKILL und damit muss das Betriebssystem/Datenbanken etc. auch umgehen koennen.

    Die Exception bad_alloc durchwerfen lassen, so hast du einen brutalen Absturz, aber das Programm räumt alles auf. abort und exit haben in C++ eher nichts zu suchen.

    Nexus schrieb:

    Führt das nicht zu Programmabstürzen? Soweit ich mich erinnern kann, haben ungefangene Exceptions in Release-Versionen immer zu Fehlermeldungen wie "Programm.exe funktioniert nicht mehr" geführt...

    Das wäre in dem Fall auch gewollt.

    Grüssli



  • Nexus schrieb:

    Hmm. Da habe ich wohl den Satz auf www.cplusplus.com falsch interpretiert:

    exit schrieb:

    Terminates the process normally, performing the regular cleanup for terminating processes.

    jo. das ist wohl der text für exit, wenn man nur c benutzt.



  • Nexus schrieb:

    hartmut1164 schrieb:

    Wenn bei den heutigen Systemen kein Heap zu allocieren ist, dann lief etwas sehr uebel

    Wieso? std::bad_alloc wird zum Beispiel auch geworfen, wenn kein genügend grosser Speicherbereich an einem Stück gefunden werden kann.

    Und das heisst, dass das Programm (oder sonst etwas) sehr schlimmes ablaeuft. Das letzte Mal, dass ich einen fragmentieren Heap sah war auf Win3.11 (muss baer sagen, dass ich seit WIN NT4 vor keiner Win-Kiste mehr sass).



  • Dravere schrieb:

    hartmut1164 schrieb:

    Mmmhh ... Jein. abort () ist soetwas wie das Zeichen fuer es ging richtig schief. Wenn bei den heutigen Systemen kein Heap zu allocieren ist, dann lief etwas sehr uebel und es ist IMHO dann besser, die Sache so brutal als moeglich abzuwuergen. Eine Datenbank sollte mit einem toten Client zurechtkommen, und auch ein noch offener File ist fuer ein Betriebssystem heute kein wirkliches Problem mehr sein - schliesslich entspricht abort () etwa dem Verhalten von SIGKILL und damit muss das Betriebssystem/Datenbanken etc. auch umgehen koennen.

    Die Exception bad_alloc durchwerfen lassen, so hast du einen brutalen Absturz, aber das Programm räumt alles auf. abort und exit haben in C++ eher nichts zu suchen.

    Ich weiss aber nicht wo der Absturz war. Bei abort () habe ich wenigstens einen core-File und kann nachsehen wo es passiert ist. Gerade dieses "Aufraeumen" vernichtet ja diese wichtige Information.

    Wie gesagt: abort () sollte reserviert sei fuer schlimme Dinge und nicht fuer "normale" Fehler.


  • Administrator

    hartmut1164 schrieb:

    Ich weiss aber nicht wo der Absturz war. Bei abort () habe ich wenigstens einen core-File und kann nachsehen wo es passiert ist. Gerade dieses "Aufraeumen" vernichtet ja diese wichtige Information.

    int *aGanzGross = NULL;
    try
    {
       aGanzGross= new int [1000000];
    }
    catch (bad_alloc&)
    {
       cerr << "Autsch" << endl;
       // Etwas ins Log speichern.
       // Nun kannst du eine weitere Exception werfen oder...
       throw; // <- Weiterwerfen
    }
    

    Du kannst eine eigene Exception dann weiterwerfen, welche zum Beispiel __LINE__ und __FUNCTION__ speichert. Du kannst alles mögliche in die Exception packen und irgendwo speichern.
    Bei einem Absturz wird ja glaub ich auch ein Minidump erzeugt. Den kann man dann analysieren.

    Edit: Ich meinte natürlich __FILE__ ... __FUNCTION__ ist nicht im Standard, wird zum Teil zwar auch unterstützt 😉

    Grüssli



  • hartmut1164 schrieb:

    Ich weiss aber nicht wo der Absturz war. Bei abort () habe ich wenigstens einen core-File und kann nachsehen wo es passiert ist. Gerade dieses "Aufraeumen" vernichtet ja diese wichtige Information.

    da mach ich dann

    __asm int 3;
    

    oder sowas spaßiges. 🕶



  • volkard schrieb:

    hartmut1164 schrieb:

    Ich weiss aber nicht wo der Absturz war. Bei abort () habe ich wenigstens einen core-File und kann nachsehen wo es passiert ist. Gerade dieses "Aufraeumen" vernichtet ja diese wichtige Information.

    da mach ich dann

    __asm int 3;
    

    oder sowas spaßiges. 🕶

    Da kann man viel machen ...

    int ErrorHandler::BrutalAbort_Count_Zero (int   iIn)
    {
            if (iIn == 0)
                    return iIn;
            else
                    return (BrutalAbort_Count_Zero (iIn - 1));
    }
    
    int ErrorHandler::BrutalAbort (void)
    {
            return ((1 + BrutalAbort_Count_Zero (3)) / (BrutalAbort_Count_Zero (BrutalAbort_Count_Zero (2))));
    }
    

    🤡

    Bisher hat noch kein Compiler gemerkt, dass ich hier eine Division durch 0 veranstalte.


Anmelden zum Antworten