Wo sollte man assert benutzen?



  • kingruedi schrieb:

    Ich denke die Diskussion macht eh wenig Sinn. Wenn Optimizer es für nötig hält ständig alles überall zu prüfen, dann bringt es auch nichts jetzt auf ihn einzureden. Auch wenn es für den Rest von uns logisch scheint, dass man Eingaben lieber am Ort der Eingabe prüft und auf den Stupiden-Prüf-Overhead im Release verzichtet.

    Ein wahres Wort. 😃
    Wie gesagt, wenn eine Prüfung mal wirklich der Flaschenhals sein sollte, dann entferne ich sie schon auch.

    @void: Ich hab mich mit Threads noch nicht auseinandergesetzt (hey ich lern grad 3 Sprachen gleichzeitig 😉 ).



  • Optimizer schrieb:

    wie gesagt, wenn eine Prüfung mal wirklich der Flaschenhals sein sollte, dann entferne ich sie schon auch.

    Und wie machst Du das, wenn zwei Projekt die Lib benutzen, die eine verläßt sich drauf, daß die Checks durchgeführt werden, für die andere ist es zu lahm... machst Du dann ne Kopie und modifizierst eine? Wie erklärst Du dann Deinem Chef, daß in Zukunft zwei Libs gewartet werden müssen? Aber auch das hatte ich oben schonmal geschrieben.

    Und jetzt geb ich es glaub ich auf.

    MfG Jester



  • 333 schrieb:

    Wo sollte man assert benutzen?

    in c.

    in c++ hat assert nix mehr zu suchen.
    a) die netten meldungen "fehler in datei sowieso.cpp in zeile 42" schicke man sich im debug-code auch seinem debugger und im release-code kommen assertions nicht vor.
    b) der harte abbruch macht ja jede fehlersuche schwer. warum nicht mit "__asm int 3" oder ähnlichem den debugger auf die kritische zeile setzen. dann kann man sofort die variablen prüfen und muß nicht erst rausfinden, wie man den fehler nochmal rekonstruieren kann.
    c) es fliegen keine destruktoren. und was ist, wenn die konsistenz meiner datenbank auch von destruktoren abhängt? also werfe man tunlichst nach dem debuggeraufruf noch ne exception und fange main grundsätzlich spätestens in der main.

    falls wir von nem neuen makro ASSERT ausgehen (schrieb man in c nicht bereits makros GROSS?), das obiges tut, dann wird die frage langsam interessant.
    dann ist ASSERT bei fehlern zu setzen, die gar nicht vorkommen können, falls der programmierer die eingaben (auch von der platte und so) korrekt abtestet. die bibliotheken werden einfach zu lahm, wenn sie idiotenfest sein sollen. idiotenfest ist zum beispiel, wenn ein stack ne exception wirft, weil er leer war und gepoppt wird. man gehe immer davon aus, daß der bibliotheksanwender programmieren kann und lasse schliche den potenziellen absturz da. in debugversion gerne ne dialogbox, ein logfile, ne exception, ein debuggeraufruf, ein signalton und ne mail an microsoft (alles in MSASSERT drin). aber im releasecode bitte keinen unfug. "zero cost" muß devise bleiben, c++ ist nicht lahmer als assembler. wer damit nicht leben kann, nehme einfach j*v*.



  • jo, dass __asm__("int $0x03"); ist schon recht sinnvoll (auch unter C :)). Deswegen kann man ja folgendes machen (für gcc/g++)

    #ifndef NDEBUG
    #undef assert
    #define assert(cond)  ((cond)?(void)0:my_assert_failed())
    #ifdef IA32
    inline void my_assert_failed() { __asm__("int $0x03"); }
    #else
    inline void my_assert_failed() { raise(SIGTRAP); } //sollte unter Unix-like systemen gehen (falls kein IA32)
    #endif
    #endif
    


  • Was macht asm int 3? Warum ruft man einen Interrupt auf wenn man an eine Codestelle springen will? Kann mich jemand aufklären?



  • mit int 3 wird der interrupt 3 aufgerufen, welcher den Debugger startet.



  • jo, wirkt wie ein Brakepoint



  • FYI: Interrupts werden auf dem 80x86 mit einem Zweibyte-Maschinencode aufgerufen, z.b. 0xCD 0x10 für Interrupt 0x10. Einzige Ausnahme ist der Interrupt 3, der auch mit einem Einzelbytebefehl, 0xCC, aufrufbar ist. Damit kann ein Debugger diesen Befehl relativ schmerzlos und stressfrei in den Maschinencode einfügen und auch wieder entfernen, was mit einem Zweibytecode nicht so ganz einfach wär.



  • kingruedi schrieb:

    jo, dass __asm__("int $0x03"); ist schon recht sinnvoll (auch unter C :)). Deswegen kann man ja folgendes machen (für gcc/g++)

    #ifndef NDEBUG
    #undef assert
    #define assert(cond)  ((cond)?(void)0:my_assert_failed())
    #ifdef IA32
    inline void my_assert_failed() { __asm__("int $0x03"); }
    #else
    inline void my_assert_failed() { raise(SIGTRAP); } //sollte unter Unix-like systemen gehen (falls kein IA32)
    #endif
    #endif
    

    im debug-code ist inline ausgeschaltet. da hat er mich leider in die my_assert_failed() geschmissen, statt auf die codezeile, wo das assert stand.



  • ohne Funktions umbau will aber leider das __asm__ keyword nicht arbeiten und mit einem STEP ist man ja da wo der assert geschmissen wurde.



  • Weiß jemand, wieso asm eine Deklaration ist?



  • Bashar schrieb:

    Weiß jemand, wieso asm eine Deklaration ist?

    Vielleicht weil eine asm-Deklaration auch auf Namespacescope-Ebene stehen darf und dort nur Deklarationen und Definitionen auftauchen dürfen. Also kann es schon mal nur eine Deklaration oder Definition sein. Da eine asm-Deklaration aber nicht über einen {}-Block verfügt bleibt es bei einer Deklaration.

    So, das war mal mein Schuss ins Blaue 🙂


Anmelden zum Antworten