Wo sollte man assert benutzen?
-
@Optimizer: Wie schade, daß Du meinen Beitrag ignorierst.
-
Ich habe doch den Test gemacht (gleich der nächste Post).
Die Methode liefert zurück, dass sie fehlgeschlagen ist.
-
Um es kurz zu machen zitiere ich mich mal eben selbst.
Jester schrieb:
Komm mal weg von Deinem DX-Beispiel, das ist aus zwei Gründen nämlich nicht repräsentativ:
-
Man mag von MS halten was man will, aber im gute Schnittstellen definieren sind sie wahrlich keine Meister. Wenn ich sehen will, wie man ne gute Lib schreibt, dann werf ich nen Blick auf die STL.
Nur weil die MFC von CObject erbt ist das nicht gleich gutes Design. -
DX ist eine Bibliothek, die direkt auf die Hardware zugreift. Sozusagen am OS vorbei. Daher ist es wichtig, daß sie falsche Aufrufe erkennt, denn damit kann man nicht nur die eigene Applikation zum Absturz bringen, sondern die Integrität des gesamten Systems beeinflussen. Und das darf ein Betriebssystem niemals zulassen.
- ist zwar etwas schwächer, aber 2) kannst Du nicht ernsthaft ignorieren, insofern verstehe ich nicht, warum Du bei dem Beispiel bleibst.
-
-
2.) Stimmt so nicht. Auf die Hardware zugreifen tun nur Treiber, das sind die einzigen Programme, die wirklich ein System zum Absturz bringen können. Wenn eine DX-Funktion auf NULL zugreift, wird sie vermutlich genauso gekickt wie jedes andere Programm.
Aber darum geht es nicht. Ich will, dass meine Libs, Klassen, whatever sicher sind, IMMER. Und ob ich jetzt dazu - wie vorgeschlagen - asserts auch im Release verwende oder eine if-Abfrage tut da nicht wirklich was zur Sache.---------
Wir drehen uns ständig im Kreis, ich habe doch bereits ausführlich dargelegt, für was ich asserts verwende. Für Situationen, die ich voll und ganz kontrollieren kann, wo meine Programmlogik sicherstellt, dass irgendetwas niemals passiert. -> asserts sind völlig "unnötig", sie erfüllen keine Funktion, sondern sind nur eine Bestätigung, dass meine Programmlogik korrekt ist.Du verwendest asserts auch, um Situationen zu kontrollieren, die du nicht vollständig unter Kontrolle hast und gehst davon aus, dass spätestens beim Release deine Lib richtig benutzt wird. Vermutlich (ein anderer Grund für diese Annahme fällt mir nicht ein) aus Performancegründen.
---------Aus Performancegründen würde ich eine Prüfung nur entfernen, wenn sie zweifelsfrei bei einer Methode der Flaschenhals ist. Ich möchte noch einmal klarstellen, dass ich die Prüfungen auch nur einmal mache. Wenn meine Methode danach noch andere, interne Methoden aufruft, gibt es keine Prüfungen mehr mit Exceptions.
1.) Zu MS und DX: Ich finde die Vorgehensweise von MS gut, sie entspricht der meinen, außer dass die wahrscheinlich wegen C mit Rückgabewerten statt Exceptions arbeiten (In Managed DX wird mit Exceptions gearbeitet).
Im Grunde sind es nur unterschiedliche Ansichten, ich will immer die Sicherheit, dass meine Lib keinen Murks baut, und verzichte nur im Zweifelsfall auf eine Prüfung. Es kommt ja gar nicht darauf an, ob ich das mit Exceptions oder sonstwie mache. Du sagst, es reicht, im Debug Build zu prüfen, dann bieten sich asserts wohl an.
-
Optimizer schrieb:
Aber darum geht es nicht. Ich will, dass meine Libs, Klassen, whatever sicher sind, IMMER.
Aus reinem Interesse, wie gehst du mit Thread-Sicherheit um?
-
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.
-
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