Exception oder Rückgabewert?



  • Dafür nimmt man dann assert.



  • akari schrieb:

    Hallo

    Mit nicht bestimmbar meine ich, wenn eine Funktion mit

    int foo(TClass *Class)
    

    mit Class == NULL aufgerufen wird, obwohl ein solcher Wert gar nicht verarbeitet werden kann.

    bis bald
    akari

    das is meiner meinung nach der job von nem assert weil der input vom programmierer kommt und der programmierer sicherzustellen hat, dass er keine null pointer übergibt

    int foo(TClass *Class)
    {
      assert ( Class != NULL );
    }
    

    in der theorie könnte sich der übergabewert im debug und release modus unterscheiden falls dem system der speicher ausgeht

    in der praxis gibts keinen unterschied wenns keine speicherintensive anwendung is



  • Shade Of Mine schrieb:

    Sovok schrieb:

    gutes beispiel is wenn man z.b. ne datei aufmacht oder speicher allokiert

    Bitte sag, dass das nicht dein ernst ist.
    da kann man ja gleich nur die return werte auslesen...

    wieso sollte man das nicht so machen? das problem ist ja, das alle standart-libs statt exception return wert liefern. ( auser der STL vieleicht )
    ich benutzt exceptions häufig um das HRESULT aus directx auszuwerten. eine einzige exception-klasse die zu dem HRESULT einen info-text ausgibt. und in der winmain steht dann ein try catch mit fehlerdialog im catch block.



  • Hallo

    Dafür nimmt man dann assert.

    Exakt. Das habe ich auch in meinem ersten Post so dargestellt, habe es nur in der Erläuterung vergessen zu erwähnen.

    bis bald
    akari



  • DEvent schrieb:

    wieso sollte man das nicht so machen? das problem ist ja, das alle stan****-libs statt exception return wert liefern. ( auser der STL vieleicht )

    bei den IOStreams kann man exceptions einschalten und C Libraries wrappt man.
    Und die anderen C++ Standard Funktionen können kaum fehlschlagen...

    wenn man
    if(foo()) throw;
    if(foo2()) throw;
    schreibt, dann kann man sich exceptions ja gleich sparen - sie bringen hier nur verdammt wenig.

    ein
    foo();
    foo2();
    ist hier viel schöner und eleganter (zudem kann man auch noch bessere exception werfen, weil man GetLastError()/errno oder sonstwas auswerten kann...



  • Merkregel: Fasse nie eine C-API roh an. 🤡 🤡 Wrap it up! 👍



  • Sovok schrieb:

    ich benutz es in dem fall nich um returnwerte nicht auslesen zu müssen, sondern um zeilen zu sparn

    die einzige alternative die mir in dem fall einfällt is goto aber des benutz ich aus prinzip ned

    Ja ganz toll: Exceptions als Ersatz für das (teilweise zu Recht) verpönte goto zu benutzen... 🙄



  • Prüft ihr pointer generell mit Assert? Ich prüfe diese immer, wenn sie NULL sein können mit nem einfachen if (!p) /*mach irgendwas*/ und Asserts verwende ich nur zum prüfen von Arraygrenzen usw. oder wenn nen Zeiger wirklich niemals NULL sein kann.

    Exceptions verwende ich dann wenn es Sinn macht z.B. wenn der Rückgabewert kein Fehlercode ist sondern ein Wert, oder wenn es wirklich eine Ausnahme ist, z.B. wenn die Rechte für eine Operation fehlen.



  • MaSTaH schrieb:

    Sovok schrieb:

    ich benutz es in dem fall nich um returnwerte nicht auslesen zu müssen, sondern um zeilen zu sparn

    die einzige alternative die mir in dem fall einfällt is goto aber des benutz ich aus prinzip ned

    Ja ganz toll: Exceptions als Ersatz für das (teilweise zu Recht) verpönte goto zu benutzen... 🙄

    ne der wesentliche unterschied is, dass man per goto überall hinspringen kann wohingegen die exception zum ende des try blocks springt
    find ich wesentlich definierter

    aber gehen wir mal zum spass von ner speicherintensiven anwendung aus bei der keine exceptions benutzt werden dürfen

    char* p1=NULL,p2=NULL,p3=NULL;
    
    //mach was
    p1 = new char[/*variabel*/];
    if ( p1 == NULL )
      //return
    //mach was
    p2 = new char[/*variabel*/];
    if ( p1 == NULL )
      //return
    //mach was
    p3 = new char[/*variabel*/];
    if ( p1 == NULL )
      //return
    

    wie würdest du hier am besten sicherstellen, dass aufgeräumt wird und gleichzeitig redundanten code vermeiden?



  • Indem ich SmartPointer verwende 😃 :p 😃

    mfg JJ



  • SirLant schrieb:

    Prüft ihr pointer generell mit Assert? Ich prüfe diese immer, wenn sie NULL sein können mit nem einfachen if (!p) /*mach irgendwas*/ und Asserts verwende ich nur zum prüfen von Arraygrenzen usw. oder wenn nen Zeiger wirklich niemals NULL sein kann.

    Exceptions verwende ich dann wenn es Sinn macht z.B. wenn der Rückgabewert kein Fehlercode ist sondern ein Wert, oder wenn es wirklich eine Ausnahme ist, z.B. wenn die Rechte für eine Operation fehlen.

    angenommen die funktion wird nicht exportiert und ich bin der einzige der damit programmiert dann ja

    ansonsten nehm ich beides

    per assert bin ich dann zur laufzeit schnell informiert in welcher zeile ich mist gebaut hab
    if an sich nur als schutz gegen unsachgemäße handhabung



  • Sovok schrieb:

    wie würdest du hier am besten sicherstellen, dass aufgeräumt wird und gleichzeitig redundanten code vermeiden?

    Mal abgesehen davon, dass new eine Exception wirft...

    //mach was
    auto_ptr<foo> p1(new Foo());
    auto_ptr<foo> p2(new Foo());
    auto_ptr<foo> p3(new Foo());
    

    RAII lässt grüßen...

    Resourcen roh anfassen ist doof.
    Notfalls gibt es ja auch noch nen StackGuard...

    @SirLant
    Was machst du denn, wenn der Zeiger 0 ist? Wie verhält sich dein Programm dann? Einfach return; damit man den Fehler schön leicht ignorieren kann?



  • Ich würde immer noch SmartPointer verwenden.
    Liest den keiner meine Postings ( 😃 😞 😃 )

    mfg JJ



  • Shade Of Mine schrieb:

    @SirLant
    Was machst du denn, wenn der Zeiger 0 ist? Wie verhält sich dein Programm dann? Einfach return; damit man den Fehler schön leicht ignorieren kann?

    Kommt drauf an je nachdem wo es passiert geb ich ne MessageBox aus oder schmeiß ne Exception.
    Assert könnte ich natürlich auch verwenden aber wenn ich nen debug-build habe brauche ich das nicht da ich da sowieso die Zeile angezeigt bekomme und die Zeiger die immer NULL sein können weil man Ressourcen anfordert die prüfe ich immer mit nem if und handle entsprechend je nachdem muss das Programm ja gar nicht beenden.



  • Sorry das ich mich erst jetzt melde, aber ich hab keine Benachrichtigung mehr bekommen 😞

    Ich geh mal auf einige Punkte ein:

    1. Exceptions sind schneller als If-Abfragen auf den Return Code

    Ganz im Gegenteil, bei Return-Werten machst du immer einer if-Abfrage, selbst wenn kein Fehler auftritt. Bei Exceptions kommst du in den catch-Block, nur wenn ein Fehler auftritt.

    Und wie kommt das Programm dann in den Catch-Block? Nur weil du kein If machst, heisst das noch lange nicht, dass der Compiler da keins macht.

    1. Asserts
      Normalerweise werden Asserts nur in Debug-Versionen hineinkompiliert. In Release Versionen werden die meistens automatisch abgeschaltet. Man muss ein Assert wie eine Sollbruchstelle sehen. "Ich vermute, da könnte ein Fehler auftreten aber wirklich abfangen kann ich nicht, oder bin zu faul für". Zumindestens denk ich so, wenn ein fremdes Programm mit einem Assert aussteigt.

    zum Beispiel wenn eine externe Datei, ein Registry-Schlüssel oder ein Server nicht erreichbar ist. Dann kann ich eine auch für den User sinnvolle Fehlermeldung ausgeben und das Programm auf jeden Fall beenden (wenn übergreifende try-Behandlung gibt)

    Das Kann ich mit einem Return Code auch. (oder mit errno 😉 ) Wobei eine Exception schon was heftiger ist, Catch or die() könnte man hier fast schon sagen, einen ungültigen Return Code kann ich in vielen Fällen ignoren, die Exception muß ich abfangen.

    aber gehen wir mal zum spass von ner speicherintensiven anwendung aus bei der keine exceptions benutzt werden dürfen

    C/C++ Code:

    char* p1=NULL,p2=NULL,p3=NULL; 
    
    //mach was 
    p1 = new char[/*variabel*/]; 
    if ( p1 == NULL ) 
      //return 
    //mach was 
    p2 = new char[/*variabel*/]; 
    if ( p1 == NULL ) 
      //return 
    //mach was 
    p3 = new char[/*variabel*/]; 
    if ( p1 == NULL ) 
      //return
    

    wie würdest du hier am besten sicherstellen, dass aufgeräumt wird und gleichzeitig redundanten code vermeiden?

    If-Blöcke schachteln, zieht zwar bescheuert aus, wäre aber eine möglichkeit

    if (p1 = new char[...])
    	{
    		if (p2 = new char[...])
    			{
    				if (p3 = new char[...])
    					{
    						//perfekt .. 
    						// mach perfide dinge
    					}
    				delete p2;
    			}		
    		delete p1;	
    	}
    	return -1;
    

    Wie ist das eigentlich, wird man eigentlich zu Try/Catch Blöcken gezwungen, wenn man eine Funktion mit throws() deklariert, also wie in Java?



  • nein. wird etwas geworfen, und du hats garkein catch drin, so geht dir das programm einfach nur den bach runter.



  • Evil Azrael schrieb:

    Und wie kommt das Programm dann in den Catch-Block? Nur weil du kein If machst, heisst das noch lange nicht, dass der Compiler da keins macht.

    Stack unwinding. Ist zwar nicht gratis - aber du hast trotzdem nicht soviele Sprünge drinnen (und es kann theoretisch gratis sein - praktisch gesehen gibt es aber keine implementierung die das kann).

    Normalerweise werden Asserts nur in Debug-Versionen hineinkompiliert. In Release Versionen werden die meistens automatisch abgeschaltet. Man muss ein Assert wie eine Sollbruchstelle sehen. "Ich vermute, da könnte ein Fehler auftreten aber wirklich abfangen kann ich nicht, oder bin zu faul für". Zumindestens denk ich so, wenn ein fremdes Programm mit einem Assert aussteigt.

    Ein assert ist nur zu Debug Zwecken da. Es fängt logikfehler des Programmierers ab. In der Release Version ist nicht mehr vorhanden (denn dann sollte es keine logikfehler mehr geben)

    Das Kann ich mit einem Return Code auch. (oder mit errno 😉 ) Wobei eine Exception schon was heftiger ist, Catch or die() könnte man hier fast schon sagen, einen ungültigen Return Code kann ich in vielen Fällen ignoren, die Exception muß ich abfangen.

    Pluspunkt für Exception.
    Oder willst du einen Fehler ignorieren?

    try/catch und die() sind vollkommen unterschiedlich.

    If-Blöcke schachteln, zieht zwar bescheuert aus, wäre aber eine möglichkeit

    Bloß nicht. Wir haben seit Jahren das RAII-Idiom - wer sowas macht, sollte lieber nach Java/C# wechseln, da hat man finally für soetwas

    Wie ist das eigentlich, wird man eigentlich zu Try/Catch Blöcken gezwungen, wenn man eine Funktion mit throws() deklariert, also wie in Java?

    Man verwendet keine Exception Spezifikationen in C++
    und checked exceptions gibt es nur in Java (ein mechanismus der sehr zweifelhaft ist)

    Exception in C++ haben generell erstmal nur sehr wenig mit try/catch zu tun.
    Tatsächlich habe ich keine 10 "try"s in meinen codes (ich rede von kompletten anwendungen).
    C++ macht es hier wesentlich anders als Java/C# - das kann man nicht vergleichen.



  • Shade Of Mine schrieb:

    Evil Azrael schrieb:

    Und wie kommt das Programm dann in den Catch-Block? Nur weil du kein If machst, heisst das noch lange nicht, dass der Compiler da keins macht.

    Stack unwinding. Ist zwar nicht gratis - aber du hast trotzdem nicht soviele Sprünge drinnen (und es kann theoretisch gratis sein - praktisch gesehen gibt es aber keine implementierung die das kann).

    Na schön, aber selbst dann muss er irgendwo gucken, ob er´s behandeln muss oder nicht, oder?
    Hast du eine Idee, wie man das "gratis" realisieren könnte?

    Normalerweise werden Asserts nur in Debug-Versionen hineinkompiliert. In Release Versionen werden die meistens automatisch abgeschaltet. Man muss ein Assert wie eine Sollbruchstelle sehen. "Ich vermute, da könnte ein Fehler auftreten aber wirklich abfangen kann ich nicht, oder bin zu faul für". Zumindestens denk ich so, wenn ein fremdes Programm mit einem Assert aussteigt.

    Ein assert ist nur zu Debug Zwecken da. Es fängt logikfehler des Programmierers ab. In der Release Version ist nicht mehr vorhanden (denn dann sollte es keine logikfehler mehr geben)

    Brauchst du mir nicht zu erklären, ich kenne die assert anweisung (oder makro).

    Das Kann ich mit einem Return Code auch. (oder mit errno 😉 ) Wobei eine Exception schon was heftiger ist, Catch or die() könnte man hier fast schon sagen, einen ungültigen Return Code kann ich in vielen Fällen ignoren, die Exception muß ich abfangen.

    Pluspunkt für Exception.
    Oder willst du einen Fehler ignorieren?

    Machmal gibt es Fehler und Warnungen, die kann man ignorieren.

    try/catch und die() sind vollkommen unterschiedlich.

    Was soll mir das jetzt sagen?

    If-Blöcke schachteln, zieht zwar bescheuert aus, wäre aber eine möglichkeit

    Bloß nicht. Wir haben seit Jahren das RAII-Idiom - wer sowas macht, sollte lieber nach Java/C# wechseln, da hat man finally für soetwas

    Was ist das RAII Idiom? Was macht finally?
    Was hast du gegen die Schachtelung ausser dass es sehr in die "Breite" geht. Mach doch einen besseren Vorschlag.

    Wie ist das eigentlich, wird man eigentlich zu Try/Catch Blöcken gezwungen, wenn man eine Funktion mit throws() deklariert, also wie in Java?

    Man verwendet keine Exception Spezifikationen in C++
    und checked exceptions gibt es nur in Java (ein mechanismus der sehr zweifelhaft ist)

    Exception in C++ haben generell erstmal nur sehr wenig mit try/catch zu tun.
    Tatsächlich habe ich keine 10 "try"s in meinen codes (ich rede von kompletten anwendungen).
    C++ macht es hier wesentlich anders als Java/C# - das kann man nicht vergleichen.

    Wieso haben Exception recht wenig mit try/catch zu tun? Über ein paar Erklärungen würd ich mich sehr freuen. Enlight me, please...



  • Evil Azrael schrieb:

    Machmal gibt es Fehler und Warnungen, die kann man ignorieren.

    Wenn du einen Fehler ignorieren kannst, dann ist es auch keiner.
    Ich weiss aber schon, es gibt API's die solche blöden Sachen machen.



  • Evil Azrael schrieb:

    Na schön, aber selbst dann muss er irgendwo gucken, ob er´s behandeln muss oder nicht, oder?
    Hast du eine Idee, wie man das "gratis" realisieren könnte?

    Nein, mir fehlt leider das Verständnis für die verschiedenen Möglichkeiten Exception zu implementieren...

    Machmal gibt es Fehler und Warnungen, die kann man ignorieren.

    zB?

    try/catch und die() sind vollkommen unterschiedlich.

    Was soll mir das jetzt sagen?

    Dass ein die() sofortigen Abbruch bedeutet und Exception lediglich Fehler melden...

    Was ist das RAII Idiom? Was macht finally?

    try/catch/finally.
    Finally wird immer ausgeführt, egal ob eine Exception geflogen ist.

    File f;
    try
    {
      f=new File("foo");
      f.write(..);
    }
    catch(Exception e)
    {
      log(e);
    }
    finally
    {
      f.close();
    }
    

    f.close() wird immer ausgeführt, egal ob ein Fehler aufgetreten ist, oder nicht.

    RAII: http://de.wikipedia.org/wiki/RAII

    Was hast du gegen die Schachtelung ausser dass es sehr in die "Breite" geht. Mach doch einen besseren Vorschlag.

    Einfach veraltet, fehleranfällig, umständlich und schwer wartbar/lesbar.

    Wieso haben Exception recht wenig mit try/catch zu tun? Über ein paar Erklärungen würd ich mich sehr freuen. Enlight me, please...

    Puh, dir fehlt scheinbar das verständnis für C++ Exception. So schnell ist das nicht erklärt.

    Kurz zusammengefasst (Exceptional C++ erklärt es vermutlich besser):
    Exception sind Ausnahmen und treten somit nur selten auf. Es geht dabei weniger um try/catch weil man mit RAII sich ein try/catch und dann weiterwerfen sparen kann. Auch ein finally ist deshalb nicht nötig.

    Die Idee ist nun: try/catch kommt nur dort vor, wo man auch wirklich eine Ausnahme behandeln kann - und das ist normalerweise nur an einigen wenigen zentralen Punkten.

    Viel mehr geht es bei Exception in C++ darum, Exception sicher zu sein - dh, trotz dem auftreten von Exception konsistent zu bleiben.

    char* p=new char[100];
    char* p2=new char[100];
    

    ist zB Fehlerhaft, weil p nicht freigegeben wird, wenn p2 fehlschlägt.

    In java würde man es so machen (C++ Code):

    char* p=0;
    char* p2=0;
    try
    {
      p=new char[100];
      p2=new char[100];
    }
    finally
    {
      delete p;
      delete p2;
    }
    

    In C++ dagegen so (mal angenommen array_ptr ist ein smartpointer ala auto_ptr nur für arrays):

    array_ptr<char> p(new char[100]);
    array_ptr<char> p2(new char[100]);
    

    wir haben jetzt exception sicherern code ohne try/catch geschrieben. und so geht es eben die meiste zeit - bis man auf den Fehler reagieren kann - was, wie gesagt normalerweise an wenigen zentralen stellen der fall ist.

    Natürlich ist da jetzt nur ein kurz überblick - wirklich lohnen würde es sich, wenn du dir die GotW durchlesen würdest (http://www.gotw.ca/gotw/) Da sind einige Artikel davon behandeln Exception.


Anmelden zum Antworten