Home | Lehre | Videos | Texte | Vorträge | Software | Person | Impressum, Datenschutzerklärung | Blog RSS

assert() oder: Bugs melden sich selbst

In Standard-C und -C++ gibt es das Makro assert(), mit dem man Vor- und Nachbedingungen und beliebige andere Checks durchführen kann:

#include <assert.h>

// Diese Funktion darf nur mit 0 oder
// einer positiven Zahl aufgerufen werden.
// Sie liefert eine strikt negative Zahl zurück.
int meineFunktion(int x)
{
    assert(x>=0); // Vorbedingung prüfen

    int y;
    y = -42-x;
 
    assert(y<0); // Nachbedingung prüfen
    return y;
}

Wird eine Bedingung verletzt, beendet assert() das Programm und gibt in der Konsole aus, welche Prüfung in welcher Zeile welcher Quelldatei fehlgeschlagen ist.

Kompiliert man mit #define NDEBUG, ist die Definition von assert() leer, das heißt, es findet keine Prüfung statt und das Programm läuft folglich mit voller Geschwindigkeit. Visual C++ verhält sich so im Release-Modus, im Unterschied zum Debug-Modus.

Komplexere Tests lassen sich schlecht in ein assert() fassen. Hier muss ausdrücklich ein #ifndef her:

#ifndef NDEBUG
// Bedingung: Alle 10000 müssen belegt sein!
int i;
for(i=0; i<10000; ++i)
{
    assert(polygon[i] != 0);
}
#endif

In Cinema4D-Plugins lässt sich das herkömmliche assert() nicht verwenden. Aber man kann sich ein eigenes definieren, das bei Fehlern z.B. in den Debugger springt:

#ifdef NDEBUG
#define assert(a)
#else
#define assert(a) if(!(a)){__asm{int 3}}
#endif

Die seltsame Klammerung !(a) ist dabei nötig, weil der Präprozessor dumm ist. Ohne Klammerung, nur mit !a, würde der Präprozessor aus

bool a, b;
// ...
assert(a&&b);

folgenden Code erzeugen:

if(!a&&b) ...