Wo sollte man assert benutzen?
-
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