(wieder einmal) try, throw und catch...



  • Ich jetzt begonnen mit dem Exception-Handling zu arbeiten. Scheint ziemlich praktisch zu sein. Vorallem was Fehler angeht, die das Programm beenden (unter anderem).

    Aber:
    Ist es legitim, wenn ich meine ganze bisherige main() (die ja eine gewisse Länge erreicht) in einen try-Block stecke und am Ende mit einem catch mögliche Fehler abfange? Ich habe dafür eine Fehler-Klasse, die in jedem kritsichen Fall geworfen wird und somit das Programm sauber beendet wird (weil in so einem Fall immer bis ans Ende der main() gegangen werden muss). Wenn nötig kann ich auch noch Interfaces oder ähnliches releasen. Das Problem ist nur, dass ich mal wo gelesen hab, dass es besser ist kleine Try-Blöcke zu machen.

    Also, sagt mal, was ihr davon haltet. ^^



  • Hm. Entweder sind sämtliche Internet-Anschlüsse ausgefallen, oder keiner will mir antworten. *lol* (Ich bin doch nicht ungeduldig!? ^^)



  • Das ist auch 'n bissl Geschmackssache.

    Je mehr kleine try / catch Bloecke Du machst, um so mehr Overhead entsteht. Umso besser kannste aber auf Fehler reagieren.

    Du willst ja nicht wegen jeder Exception das ganze Programm (geordnet) beenden.

    Stell Dir mal vor, du willst 'ne Graphik- Datei laden und dabei kommt's zu einem fehler (Dateiinhalt kaputt....). Da waer's doch gut gezielt (in Try) darauf zu reagieren und weiterzuarbeiten. - Meldung ausgeben, andere Datei waehlen, das Ganze nochmal probieren.



  • Ist es legitim, wenn ich meine ganze bisherige main() (die ja eine gewisse Länge erreicht) in einen try-Block stecke und am Ende mit einem catch mögliche Fehler abfange?

    Sicher.

    Das Problem ist nur, dass ich mal wo gelesen hab, dass es besser ist kleine Try-Blöcke zu machen

    Da man nur kurze Methoden schreibt, sind selbstverständlich auch die try-Blöcke klein.



  • Du willst ja nicht wegen jeder Exception das ganze Programm (geordnet) beenden.

    Schon klar. 😉 Aber bei Speicher-Problemen scheint mir das am vernünftigsten.

    Da man nur kurze Methoden schreibt, sind selbstverständlich auch die try-Blöcke klein.

    Hm. Da hast du schon recht. Aber ich hab gemeint, dass der ganze Inhalt der main() (bis auf die folgenden catch-Blöcke) in einem einzigen try ist. Da ist dann ja eigentlich das ganze Programm drinnen (anstelle einer 'kleinen Funktion'). Das ist natürlich nur für die wirklich harten Fehler, die das Programm beenden. Kleinere try-catch-Blöcke für kleinere Fehler sind dann noch in den einzelnen Funktionen dabei.

    Ich nehm mal an, du hast das so gemeint. - Sags, wenn ich falsch liege. -""



  • Na dazu hab ich doch auch glatt ne Frage ...
    I hab nämlich gerade den Stack-Trace für unser kleines Progrämmchen geschrieben.
    Auf Grund dessen ist es nötig in jeder nicht nothrow Methode einen Try-Catch Block zu haben ...

    Jede Methode in der irgendwie eine Exception auftreten KÖNNTE (auch in Unterfunktionen etc...)sieht also so aus ...

    void Foo::Bar()
    {
    try
    {
    // do something
    }
    catch(...)
    {
    // bla
    }
    }
    

    Wirkt sich das negativ auf die Performance aus ? (Im NOrmalfall, nicht wenn eine Exception geschmissen wird)

    Falls also irgendwo eine Exception geschmissen wird wird durch die einzelnen catch Blöcke ein StackTrace zum besseren Debuggen angelegt.
    Frisst das Performance ?
    Meine Überlegung war das die zusätzlichen Infos die der Compiler für Exceptions erstellt sowieso in den Unterfunktionen erstellt werden wenn irgendwo in den Unterfunktionen die Möglichkeit eines throws besteht.

    Also dürften diese zusätzlichen try und catch Blöcke doch nichts ausmachen, oder ?



  • Es ist auf jeden Fall gut, wenn du kleinere Fehler, die das Programm nicht beenden, an den entsprechenden Stellen behandelst. Du kannst größere fatale Fehler in einem try/catch-Block abfangen, der den gesamten Code deiner main-Funktion enthält.

    @ChaosAngel: Du musst auch in nothrow-Funktionen einen try/catch-Block haben, wenn die Möglichkeit besteht, dass eine Funktion, die von deiner nothrow-Funktion aufgerufen wird, oder der Code selber eine Exception auslöst. Zu deiner Frage kann ich nur sagen, dass es wohl kaum etwas an der Performance deines Codes ändert: Erstens ist der Overhead durch Exception-Handling auch nicht so groß, zweitens kann es sowieso sein, dass dein Compiler das try/catch rausoptimiert, wenn eh nichts passieren kann und du entsprechende Schalter aktivierst. Drittens kannst du das mit dem StackTrace auch bei den meisten Compilern abstellen, beim GCC z.B. mit "-fomit-frame-pointer".



  • ich glaube mich zu erinnern bei Meyers mal gelesen zu haben, dass heutige Compiler fast bis garkeinen overhead bei try-catch blöcken haben (ältere hatten massiven overhead)

    aber wozu so viele try catch blöcke?

    Ich mache ein try catch nur dort wo ich auf das problem reagieren kann...

    zu der ursprünglichen frage:
    ich mache oft soetwas:

    int main()
    {
    App app;
    try
    {
    app.run();
    }
    catch(whatever)
    {
    }
    }

    also ist im grunde ein großes try da.



  • Du musst auch in nothrow-Funktionen einen try/catch-Block haben, wenn die Möglichkeit besteht, dass eine Funktion, die von deiner nothrow-Funktion aufgerufen wird, oder der Code selber eine Exception auslöst.

    Darf sie denn dann noch nothrow sein ? I glaube nicht !

    Erstens ist der Overhead durch Exception-Handling auch nicht so groß,

    Wenn es in jeder Funktion auftritt dann vielleicht schon, aber in der Vector Klasse oder so kann es sowieso weggelassen werden, da passiert ja eh nichts ...

    dass dein Compiler das try/catch rausoptimiert, wenn eh nichts passieren kann und du entsprechende Schalter aktivierst.

    Das hoffte ich ...

    Drittens kannst du das mit dem StackTrace auch bei den meisten Compilern abstellen, beim GCC z.B. mit "-fomit-frame-pointer".

    Dann kann ich doch keine Exceptions mehr benutzen !

    aber wozu so viele try catch blöcke?

    Für nen manuellen StackTrace, so wie es in Unreal2003 ist wenn ne Exception geworfen wird, da wird RunTime angezeigt durch welche Funktionen er geht bei der Exception behandlung.



  • @ChaosAngel
    Das kommt auf den Compiler drauf an. Beim MSVC 6.0 sind Exceptions z.B. recht teuer. Und zwar selbst, wenn überhaupt keine Exceptions geworfen werden.

    Ansonsten sollte Exception-Handling aber erst in dem Moment etwas kosten, wo eine Exception geworfen wird. Das ist aber wiederum meist nicht weiter tragisch, da die wenigsten Leute es in solchen Situationen eilig haben 🙂

    Jede Methode in der irgendwie eine Exception auftreten KÖNNTE (auch in Unterfunktionen etc...)sieht also so aus ...

    void Foo::Bar()
    {
    try
    {
    // do something
    }
    catch(...)
    {
    // bla
    }
    }
    Wirkt sich das negativ auf die Performance aus ?

    Das wirkt sich vorallem negativ auf den Lesefluss aus.

    Darf sie denn dann noch nothrow sein ? I glaube nicht !

    Sicher. In C++ gibt es kein compile-Zeit-Check für Exceptions. Versucht eine Exception eine Funktion die mit nothrow-spezifiziert wurde zu verlassen, wird std::unexpected aufgerufen. Diese Funktion ruft standardmäßig std::terminate auf.

    Für nen manuellen StackTrace, so wie es in Unreal2003 ist wenn ne Exception geworfen wird, da wird RunTime angezeigt durch welche Funktionen er geht bei der Exception behandlung.

    Im CUJ waren im April 2002 zwei interessante Artikel zum Thema Tracing-Exceptions. Einer ist Online: http://www.cuj.com/articles/2002/0204/0204c/0204c.htm?topic=articles

    Der andere "Tracing Exceptions with an Exception Stack" leider nicht. Dafür gibt es hier den Beispielcode.



  • Den Artikel kannte ich schon, danke...

    Das ganze ist in Macros gekapselt, nicht unbedingt schön, aber notwendig ...
    Und i hoffe einfach mal das der Intel Compiler das gut optimiert ...



  • Das ganze ist in Macros gekapselt, nicht unbedingt schön, aber notwendig ...

    Das gilt für den ersten Artikel. Bei dem anderen, wo es um die Verfolgung von Exceptions über einen eigenen Exception-Stack geht, gibt es nicht ein einziges Makro.


Anmelden zum Antworten