17 Fehlersuche mit Standard-C
Im Sprachumfang von Standard-C ist eine portable, einfache und
sehr praktische Hilfe zur Fehlersuche vorgesehen: ein Makro
namens assert().
assert()
ist in assert.h definiert.
Es wird nur expandiert, wenn NDEBUG
nicht definiert ist.
Mit assert()
kann man Bedingungen überprüfen, die zur
Laufzeit logisch wahr
sein sollen und ansonsten auf Programmfehler hinweisen (sogenannte Invarianten).
Falls die angegebene Bedingung entgegen aller Erwartung nicht erfüllt ist, wird das Programm abgebrochen.
Nach Entfernung der Programmfehler setzt man #define NDEBUG
ein und hat
damit alle Überprüfungen ausgeschaltet; die assert()
-Aufrufe
brauchen nicht entfernt zu werden.
Beispiel: Das Programm assdemof.c
/* assdemof.c 30. 7.95 kw
*/
#include <assert.h>
#include <stdio.h>
#define IMAX 10
int feld[IMAX];
/* zeige( index ) zeigt den Wert von feld[index]:
*/
void zeige( int index )
{
assert( index<IMAX ); /* vergewissern ob index innerhalb */
assert( index>=0 ); /* der Feldgrenzen liegt */
printf( "feld[%d] = %d\n", index, feld[index] );
}
main()
{
int i;
for( i=0; i<IMAX; i++ )
{
feld[i] = 2*i;
}
zeige( -2 );
zeige( 5 );
zeige( 10 );
}
enthält zwei Fehler. Sowohl mit zeige( -2 ) als auch mit
zeige( 10 )
wird versucht, außerhalb der zulässigen Feldgrenzen
auf feld[]
zuzugreifen.
Stattdessen wollte der Programmierer eigentlich den 2., den 5. und den
letzten (also den 9.) Wert des Feldes wissen.
Das Programm erzeugt in dieser Form nach dem Übersetzen, Linken und
Starten die Ausgabe
assdemof: assdemof.c:16: zeige: Assertion `index>=0' failed.
und bleibt stehen, weil in Zeile 16 die Bedingung
index>=0 verletzt wurde31.
Angenommen, man kommt durch diesen Hinweis auf den Tippfehler
zeige( -2 ) und
korrigiert die Zeile zu zeige( 2 ), dann
erhält man -nach erneutem Kompilieren- die Ausgabe
feld[2] = 4
feld[5] = 10
assdem2f: assdem2f.c:15: zeige: Assertion `index<10' failed.
und stellt vielleicht fest, daß das letzte Feldelement nicht mit
zeige( 10 ),
sondern vielmehr mit zeige( 9 ) oder besser mit
zeige( IMAX-1 ) auszugeben
ist.
Nach der Korrektur hat man das Programm
/* assdemok.c 30. 7.95 kw
*/
#include <assert.h>
#include <stdio.h>
#define IMAX 10
int feld[IMAX];
/* zeige( index ) zeigt den Wert von feld[index]:
*/
void zeige( int index )
{
assert( index<IMAX ); /* vergewissern ob index innerhalb */
assert( index>=0 ); /* der Feldgrenzen liegt */
printf( "feld[%d] = %d\n", index, feld[index] );
}
main()
{
int i;
for( i=0; i<IMAX; i++ )
{
feld[i] = 2*i;
}
zeige( 2 );
zeige( 5 );
zeige( IMAX-1 );
}
und erhält die Ausgabe:
feld[2] = 4
feld[5] = 10
feld[9] = 18
Damit kann das Programm als fehlerfrei angesehen werden und durch Einfügen
der ersten Zeile:
#define NDEBUG
#include <assert.h>
#include <stdio.h>
...
werden alle assert()
-Aufrufe ungültig und stören nicht weiter.
Insbesondere erzeugen sie nicht mehr Programmcode, als wenn sie gar nicht
vorhanden wären.
Bei später auftauchenden Fehlern kann man alle assert()
-Aufrufe
wieder aktivieren, indem man die Zeile #define NDEBUG entfernt
(oder auskommentiert) und den Quelltext neu kompiliert.
AnyWare@Wachtler.de