Compiler-Warnungen filtern und nutzen

Compiler-Warnungen sind gut. Weniger als „-Wall“ zu verwenden sollte in den wirklich tollen Unternehmen(tm) ein Kündigungsgrund sein. So viel zur Theorie, aber was wird mit den endlosen Listen von Warnungen gemacht? Meistens nichts. Der Code läuft und ist in seltenen Fällen vielleicht sogar gut entworfen, warum also mäkligen Compilern nachputzen? Ein kleines Beispiel aus meinem aktuellen Projekt.

Zu implementieren ist der Bytecode-Handler für „anewarray“ in einer Java VM (selbstverständlich in C geschrieben). Wie der Spezifikation des Bytecodes entnommen werden kann, muss dabei unter anderem eine Variable „count“ vom Stack genommen werden. Sie stellt eine vorzeichenbehaftete Zwei-Byte-Ganzzahl dar. Wenn sie kleiner als Null ist, soll eine Exception ausgelöst werden. Dieser Spezifikation bin ich selbstverständlich gefolgt und habe auch die Überprüfung für die Exception eingebaut. Leider habe ich „count“ vom Stack genommen und in einer nicht-vorzeichenbehafteten Variablen gespeichert, so dass negative Zahlen zu sehr großen positiven wurden. gcc hat mich freundlicherweise daraufhingewiesen, in dem er zu „if (count < 0)“ die hilfreiche Warnung „comparison is always false due to limited range of data type“ ausgab. Das war zwar weder ein weltbewegender Bug noch wäre er besonders schwer zu entdecken, wenn er denn wirklich mal auftreten sollte, aber es war eben doch ein Bug, und gcc hat mich beim ersten Kompilieren darauf hingewiesen. Leider haben Compiler-Warnungen die Angewohnheit, in Horden aufzutreten, das Terminal zu überfluten und nicht lockerzulassen, bis „-Wall“ wieder aus dem Makefile verschwindet. Im obengenannten Projekt gehören viele Warnungen der unused-parameter-Spezies an und stehen damit im Zusammenhang, dass manche Funktionen je nach Ziel-Platform nicht implementiert sind, also leer. Deren Parameter werden dann selbstverständlich nicht verwendet, aber das ist auch richtig so: Wenn das Board keine LEDs hat, kann ich wenig mit dem Parameter anfangen, der angibt, welche LEDs leuchten sollen. Um diese false positives abzufangen, gibt es bei C++ einen schönen Trick: Der Name des Parameters wird einfach weggelassen. Das produziert in C einen ausgewachsenen Compiler-Fehler, aber dafür unterstützt gcc das Attribut „__attribute__((unused))“, mit dem Parameter und andere Variablen als „wird möglicherweise nicht verwendet“ markiert werden können. Ein Präprozessor-Makro, gefunden bei Martin Pool, verpackt das ganze schön:

#if defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(S_SPLINT_S)
# define UNUSED(x) /*@unused@*/ x
#else
# define UNUSED(x) x
#endif

Splint kennt ein ähnliches Attribut, das hier auch gleich verwendet wird. Ebenso gut funktioniert es, den Parameter scheinbar zu verwenden, bsw. mit einem „(void) param;“ am Anfang der Methode.

Um Code überhaupt erstmal lesbar zu machen, ist übrigens Artistic Style sehr nützlich, und wem gcc noch nicht genug Warnungen auswirft, der mag Interesse an Splint haben. Beide Werkzeuge sind in Debian als Package erhältlich. Damit ist die statische Code-Analyse aber auch weitgehend ausgeschöpft.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.