exit und return



  • ich benutze zum beenden von programmen immer return. aber wenn ich in einer funktion return benutze gibt sie ja nur an die main funktion etwas zurück, soll ich dann exit benutzen um zu sagen du sollst das programm sofort schließen?
    denn sonst müsste ich ja etwas zurück geben was dann erst getestet werden müsste und dann würde erst das Porgramm geschlossen.
    danke für antworten.



  • mir ist der sinn des sofort beendens nicht ganz klar. das sollte eigenltich keine funktion solche macht haben^^. vor allem wenn noch speicher irgendwo durch dynamische strukturen frei gegeben werden solle tc. dann lass dir lieber nen bool-wert zurückgeben, ob das programm beendet werden soll und beende per hand, ist sauberer^^.



  • return beendet nur die aktuelle Funktion, d.h. das Hauptprogramm ist dafür verantwortlich, den Rückgabewert (wenn vorhanden*) auszuwerten und sich dann selber zu beenden.

    exit() beendet direkt das gesamte Programm - ohne Umwege. Das hat sowohl Vorteile als auch Nachteile (wenn du alle deine Funktionen mit exit() verlässt, werden sich deine Kollegen bestimmt darüber freuen :D).

    * wenn du keinen Rückgabewert brauchst, kannst du auch eine void-Funktion (in anderen Sprachen gern als "Prozedur" bezeichnet) verwenden.



  • Eigentlich ist es nicht die Aufgabe einer tief verschachtelten Funktion ein Programm zu beenden. Natürlich kannst du dies aber mit exit tun. Nur sollte man sich natürlich im Klaren darüber sein das dies nicht unbedingt sauber ist, schließlich übersieht man die Stelle evtl. später, da sie an einer ganz merkwürdigen Stelle ist und weiß nachher nicht mehr was da eigentlich los ist, warum sich das Programm ständig beendet. 😉

    return ist nur für Funktionen/Methoden, nicht für das eigentliche Programm.



  • Fellhuhn schrieb:

    return ist nur für Funktionen/Methoden, nicht für das eigentliche Programm.

    dies sehe ich nicht so.



  • sothis_ schrieb:

    Fellhuhn schrieb:

    return ist nur für Funktionen/Methoden, nicht für das eigentliche Programm.

    dies sehe ich nicht so.

    Falls du return in main meinst: main ist auch eine Funktion.



  • Fellhuhn schrieb:

    sothis_ schrieb:

    Fellhuhn schrieb:

    return ist nur für Funktionen/Methoden, nicht für das eigentliche Programm.

    dies sehe ich nicht so.

    Falls du return in main meinst: main ist auch eine Funktion.

    und ein return aus main lässt das programm cleanup code ausführen und das
    programm wird beendet. sorry, aber vielleicht steh' ich ja gerade auf dem
    schlauch. auch du solltest vielleicht genauer erklären was du meinst 😃



  • ich benutze eigentlich immer return. nur ich wollte das programm sofort beenden, wenn eine funktion eine bestimmte aktion nicht ausführen kann, also nur in ausnahme fällen. oder soll ich das trotzdem lieber über return in main machen und dann mit bool werten arbeiten?



  • Wenn das ein Ausnahmefall im Sinne eines Fehlers ist, kannst du ja eine Exception werfen. Dafür sind sie ja da.



  • ich glauzb ich hab jetzt eine lösung gefunden mit hilfe von einer schleife und einem bool wert,
    aber das mit einer exception müsste ich mir erst durchlesen das ahbe ich nämlich noch nie gemacht und richtig angeschaut.



  • tweenki schrieb:

    ...das mit einer exception müsste ich mir erst durchlesen das ahbe ich nämlich noch nie gemacht und richtig angeschaut.

    Tu das !!!
    Kostet Dich vermutlich weniger Zeit, als auf breiter Ebene Returnwerte einzuführen und auszuwerten und bringt Dir hinterher einfachere/klarere/kürzere Programme.

    Gruß,

    Simon2.



  • ist es sehr schlimm wenn man nicht kapiert wie man exceptions initialisiert? ich kapier dabei gar nichts nur das amn das in try und catch blöcke machen muss. und dann löst sich der stack auf. kennt jemand ein tut wo das gut erklärt wird?



  • Zeig doch mal, was du bisher erreicht hast.

    Im Allgemeinen mußt du zwei Seiten betrachten:

    Werfer - erzeugt eine Exception und schmeißt sie dann den Aufrufstack hinunter. (theoretisch kannst du fast alles werfen, was du in die Hände bekommst, aber C++ bietet die std::exception-Hierarchie dafür an)

    void meine_funktion()
    {
      ...
      if(fehler)
        throw std::runtime_error("hier ist was schiefgelaufen");
      ...
    }
    

    Fänger - ruft (direkt oder indirekt) deine Funktion auf und fängt und verarbeitet alle ankommenden Exceptions (normalerweise nur die vom richtigen Typ)

    try
    {
      ...//ziemlich viel Code - irgendwo hier drin wird 'meine_funktion()' aufgerufen
    }
    catch(std::exception& ex)
    {
      cerr<<"Fehler: "<<ex.what();
    }
    catch(...)
    {
      cerr<<"unbekannter Fehler";
    

    (what() ist eine Hilfsmethode von std::exception und gibt aus, was für ein Fehler aufgetreten ist - in diesem Beispiel wird der String ausgegeben, den du beim throw hingeschrieben hast)

    normalerweise gibst du in der catch-Klausel den Typ an, den du auffangen willst (std::exeption& schließt auch dessen Kindklassen mit ein) - die Angabe ... reagiert auf alle unbekannten Fehler (s.o. - throw kann nahezu alles werfen) - hat allerdings keine Möglichkeit mehr, etwas genaueres zu erfahren als "hier kam eine Exception".



  • in c++ in 21 Tagen wird das irgendwie ganz anders erklärt. ich kapier des dort jedenfalss nicht.
    zu was zählt man alles exceptions? fehlerhaffte eingaben oder was sonst. weil fehler haftze eingaben kann man ja mit hilfe von if fragen und so wieder korrigieren.
    mein konkretes problem ist das ich einen server programmieren möchte und dann muss man schließlich fehler beachten, zb wenn ich einen socket erstelle, dann kann das auch schief laufen und dann muss ich das irgendwie mitteilen.



  • Als Exception kannst du alles werten, was den normalen Programmablauf stört - sie werden aber normalerweise eingesetzt, wenn du dort, wo du den Fehler bemerkst, nicht sinnvoll reagieren kannst.
    (wenn der Dialog nach der Eingabe selber überprüft, ob die Eingaben korrekt sind, kann er auch reagieren - und den User um Korrektur bitten. Irgendwo tief im Inneren deiner Mathe-Bibliothek kannst du bei sinnlosen Eingabedaten nur noch eine Exception werfen (oder sinnlose Ausgaben fabrizieren))



  • also sind exceptions nur in tief verschachtelten situationen wirklich sinnvoll?



  • das muß nicht unbedingt "tief" sein (btw, ab wann gilt eine Situation als "tief verschachtelt"), das reicht schon, wenn der Fehler in einer direkt aufgerufenen Funktion auffällt:

    double sqrt(double x)
    {
    /*
      die Funktion hat keine Ahnung, woher der übergebene Wert stammt - oder was sie
      mit ungültigen Werten machen sollte, also wirft sie eine Exception und übergibt damit
      dem Aufrufer die Verantwortung
    */
      if(x<0)
        throw std::invalid_argument("keine Wurzeln aus negativen Zahlen erlaubt");
      ...
    }
    
    ...
    double input;
    cin>>input;
    /*
      wenn du jetzt schon merkst, daß du mit der Eingabe nicht weiterrechnen
      könntest, kannst du noch vernünftig reagieren und den Nutzer aufmerksam machen
    */
    cout<<sqrt(input);
    ...
    


  • tweenki schrieb:

    in c++ in 21 Tagen wird das irgendwie ganz anders erklärt. ich kapier des dort jedenfalss nicht...

    Sorry, aber das liegt in der Natur der wirklich schlechten Buchreihe.

    Zum Exceptionhandling:

    Eine Exception sollte man an dem Punkt auslösen (Strichwort: throw) wo ein Fehler auftritt, der nicht direkt an dieser Stelle behandelt wird wo er eintritt.

    Auf eine Exception sollte man an der Stelle reagieren wo man sie sinnvoll behandeln kann.

    Nehmen wir einfach mal als Beispiel das du einige Mathefunktionen in einen eigenen Header ausgelagert hast, damit du sie unter verschiedenen Umgebungen benutzen kannst. Damit du nicht von der GUI abhängig bist und sie wirklich überall verwenden kannst, ist es nicht möglich bei einer fehlerhaften Übergabe (z.B. eine 0 beim Dividenten) den Anwender zu bitten die Zahl korrigiert einzugeben. Da du also in der Funktion keine Möglichkeit hast Sinnvoll auf den Fehler zu reagieren, musst du eine andere Möglichkeit anbieten wie man auf diesen Fehler reagieren kann.

    Bei den klassischen Rückgabewerten hast du das Problem das sie zum einen den Rückgabewert belegen (im Falle einer Mathematischen Funktion hätte ich gerne die Möglichkeit einige Aufrufe zu schachteln) und auch schnell vergessen werden können. Eine andere Möglichkeit wäre z.B. den Fehlercode als Referenz in den Parametern mitzuführen. Aber grade an dem Beispiel der geschachtelten Funktionen bekommt man hier ggf. das Problem das eine fehlerhafte Rückgabe andere verherende Auswirkungen in weiteren Funktionen mit sich bringt.

    Also was macht man: Man löst im Fehlerfall in der entsprechenden Funktion eine Exception aus. Dadurch wird der Programmfluß an dieser Stelle abgebrochen (Anweisungen die danach kommen werden nicht mehr beachtet, lokal erzeugte Objekte aber bereinigt [Achtung: Kein delete bei Pointern - Ich liebe Smartpointer]) und erst mit dem catch des aktiven try-Blockes weitergemacht. Wenn man den exceptions noch unterschiedliche Typen verpasst, kann man diese auch Unterschiedlich in den catchblocken behandeln.

    cu André



  • tweenki schrieb:

    ...
    zu was zählt man alles exceptions? ....

    Mach's Dir doch nicht so schwer !
    Dir ging es doch um eine konkrete Situation, in der Du sagst "Hier will ich gar nicht mehr weitermachen" ... und da wirfst Du halt eine Exception.

    Eine "allgemeingültige und vollständige" Regel gibt's sowieso nicht. Davon zeugen z.B. die ewig langen Threads zu diesem Thema hier im Forum.
    Am Besten machst Du erstmal selbst Erfahrungen mit dem Thema.

    Gruß,

    Simon2.



  • tweenki schrieb:

    kennt jemand ein tut wo das gut erklärt wird?

    Eine Exception wirft man immer dann, wenn (Design by Contract sollte man im Hinterkopf haben) man die Postcondition einer Funktion/Methode nicht einhalten kann.

    Was den konkreten Einsatz von Exceptions anbelangt. Unbedingt die Bücher von Herb Sutter anschauen, da man einige Regeln beachten muß, damit die eigenen Klassen exception safe bzw. exception neutral sind.

    Wenn eine Exception geworfen wird, beginnt das sogenannte "stack unwinding", alle Objekte auf dem Stack werden destruiert und die Ausführung "springt im Stack zurück" solange bis irgend eine Stelle im Programm die Exception abfängt. Im schlimmsten Fall wird das Programm terminiert. Leider sind Zeiger PODs und damit passiert mit ihnen exakt gar nichts, es können so Speicherlöcher entstehen. Deshalb sollte man SmartPointer o.ä. einsetzen. Was alles zu beachten ist steht in recht gut erklärt in den Büchern von Sutter.


Log in to reply