Zesstra | e28b34f | 2021-08-21 23:04:07 +0200 | [diff] [blame^] | 1 | NAME |
| 2 | assert |
| 3 | |
| 4 | SYNTAX |
| 5 | assert (expr, msg) |
| 6 | |
| 7 | DESCRIPTION |
| 8 | |
| 9 | Wenn man ein Programm schreibt, ist es oft eine gute Idee, an |
| 10 | wichtigen Stellen Pruefungen auf grundlegende Annahmen (oder |
| 11 | "unmoegliche" Fehlerzustaende) zu formulieren. |
| 12 | |
| 13 | Beispiele hierfuer koennten Pruefungen darauf sein, ob an eine |
| 14 | Funktion die richtigen Daten uebergeben wurden oder aus einer Property |
| 15 | die richtige Datenstruktur ausgelesen wurde oder ob eine Annahme |
| 16 | stimmt, von der die Magierin ausgeht und die wichtig ist fuer den |
| 17 | weiteren Ablauf. |
| 18 | |
| 19 | Das 'assert'-Makro ist eine bequeme Moeglichkeit, solche Pruefungen |
| 20 | zu formulieren, welche an dieser Stelle einen Laufzeitfehler |
| 21 | ausloesen, falls <expr> unwahr sein sollte. Oder anders: es dient |
| 22 | dazu, die Annahme der Programmierin zu pruefen, dass <expr> in diesem |
| 23 | Moment != 0 ist. |
| 24 | In der Fehlermeldung wird in diesem Fall die aktuelle Datei, Zeile, |
| 25 | ggf. Funktion und die vom Benutzer formulierte <msg> ausgegeben. |
| 26 | Sollte einem nichts sinnvolles einfallen, schreibt einfach einen |
| 27 | String mit der <expr> rein. |
| 28 | |
| 29 | Hierbei sollte man aber bedenken, ob es an dieser Stelle gut ist, die |
| 30 | Programmausfuehrung hart abzubrechen oder es notwendig sein koennte, |
| 31 | zunaechst "aufzuraeumen", um inkonsistente Zustaende spaeter zu |
| 32 | vermeiden. assert() sollte nur verwendet werden, wenn der Abbruch der |
| 33 | Programmausfuehrung an dieser Stelle eine *sinnvolle* Reaktion auf den |
| 34 | Fehlerzustand ist. |
| 35 | Es ist moeglich, dass assert() in ein catch(...;publish) zu |
| 36 | formulieren, um eine Fehlermeldung zu produzieren, aber die |
| 37 | Ausfuehrung fortzusetzen. Aber auch bitte ueberlegen, ob das sinnvoll |
| 38 | ist. |
| 39 | |
| 40 | Das Makro ist in dem Systemheader <assert.h> definiert, welche also |
| 41 | zuvor inkludiert werden muss. |
| 42 | |
| 43 | Es ist moeglich, in einem File alle assert() auf einmal abzuschalten, |
| 44 | indem vor dem Inkludieren von <assert.h> das Define NDEBUG definiert |
| 45 | wird (egalf auf welchen Wert). Das hat den Vorteil, dass man sie |
| 46 | spaeter (z.B. zum Debuggen) schnell wieder einschalten kann. |
| 47 | |
| 48 | Der Ausdruck <expr> sollte *keinerlei* Seiteneffekte haben. Dies ist |
| 49 | speziell wichtig, wenn NDEBUG spaeter gesetzt wird, weil in dem Fall |
| 50 | auch der Seiteneffekt nicht mehr stattfindet: <expr> wird dann gar |
| 51 | nicht mehr ausgewertet. Beispielsweise ist assert (++i > 0); oder |
| 52 | assert (data = QueryProp(FOO)); eine sehr schlechte Idee. |
| 53 | Ohnehin waeren Ausdruecke mit Seiteneffekt sehr schlechter Stil. |
| 54 | |
| 55 | |
| 56 | EXAMPLE |
| 57 | |
| 58 | // Pruefung auf Vorraussetzungen einer Funktion |
| 59 | // Eine Funktion zum Bezahlen von Geld verlaesst sich darauf, dass sie |
| 60 | // nur mit positiven Werten gerufen wird. Wenn jemand sie mit |
| 61 | // negativen Werten ruft, kommt Unsinn dabei raus. |
| 62 | void pay(int money) { |
| 63 | assert(money > 0, "Negativen Betrag erhalten"); |
| 64 | ... |
| 65 | // Bemerkung: man sollte keine Benutzereingaben mit assert() pruefen! |
| 66 | |
| 67 | // Eine Funktion darf nur in leeren Raeumen gerufen werden und geht |
| 68 | // auch davon aus, dass der Raum leer ist: |
| 69 | int dispose_me() { |
| 70 | assert(!sizeof(all_inventory()); "Raum nicht leer!"); |
| 71 | remove(1); |
| 72 | } |
| 73 | |
| 74 | SEE ALSO |
| 75 | raise_error(E), throw(E) |
| 76 | |