![]() |
|
|
Sind Sie verantwortlich für die Entwicklung von Software unter Benutzung von C oder C++? Dann sind die folgenden Informationen für Sie wichtig. Die Themen, um die es im folgenden geht:
Software-Entwickler verbringen einen erheblichen Teil Ihrer Zeit damit, Fehlern in ihren Programmen nachzuspüren. Allen geht es so den guten Entwicklern nur weniger häufig. Der damit verbundene Aufwand kann beträchtlich sein; Sie werden es aus eigener, leidvoller Erfahrung wissen.
Das müßte doch eigentlich zur Konsequenz haben, ein Tool zur Code-Analyse einzusetzen: ein Programm, das Fehler in der Software findet. Jedes auf diesem Wege aufgedeckte Problem kann dem Entwickler Stunden oder gar Tage der Suche ersparen. Warum geschieht es nicht?
Da ein derartiger Einsatz weder schwierig noch teuer ist, vermute ich, daß entsprechende Tools in Deutschland nicht bekannt sind. Deshalb möchte ich Ihnen PC-Lint vorstellen.
Stellen Sie sich ein Programm vor, das über eine Art Wissensbasis verfügt, in der alle möglichen Fehler enthalten sind, die Software-Entwicklern unterlaufen können. Dieses Programm analysiert nun den Quell-Code und prüft, ob sich darin einer der ihm bekannten Fehler verbirgt. PC-Lint existiert seit 1984 und ist in diesen Jahren kontinuierlich verbessert, d.h. seine Wissensbasis ständig erweitert worden.
Ein kurzes Beispiel soll hier zur Erläuterung ausreichen:
int f( int n)
{
int result;
if (n == 1) result = 0;
else if (n > 0) result = 1;
else if (n < 0) result = 2;
return result;
}
Eine Funktion f erhält einen Parameter n. In Abhängigkeit des Wertes von n wird die (interne) Variable result auf 0, 1 oder 2 gesetzt. Zum Schluß wird das Ergebnis (result) zurückgegeben.
Nichts spektakuläres, nichts besonders schwieriges, eine Alltags-Funktion. Leider enthält sie auch einen Alltags-Fehler. Läßt man PC-Lint das Programm analysieren, dann meldet es für die Zeile return result;:
Variable 'result' may not have been initialized
Tatsächlich, wenn man aufgrund dieses Hinweises noch einmal genauer hinschaut, dann sieht man, daß ein Fall durch die if-Anweisung nicht abgedeckt wird: Ist n = 0, dann ist keine der Bedingungen erfüllt, und result wird nicht explizit auf einen Wert gesetzt. Trotzdem wird ein Wert zurückgegeben. Welcher? Was immer der zufällige Inhalt dieser Variablen war, vielleicht 0, vielleicht 27856. Es ist undefiniert und i.d.R. auch nicht reproduzierbar.
In den meisten Fällen dürfte solch ein Fehler harmlos sein und dem Entwickler bei seinen Tests irgendwann auffallen. Aber es kann auch anders kommen: Es gab mal eine Situation, an die ich auch heute noch sehr, sehr ungern zurück denke - eine Situation, die sich letztlich auf genau diesen Fehler zurückführen ließ (falls es Sie interessiert, lesen Sie die ganze Geschichte).
PC-Lint findet diesen und Hunderte anderer Fehler und
weist den Entwickler darüber hinaus auf potentiell problematische Konstruktionen hin.
Nicht jeder dieser Hinweise wird eine (Software-) Katastrophe verhindern, aber manch einer
vielleicht schon. Doch in jedem Fall wird der Entwickler durch die Hinweise des
"Experten" Lint auf bestimmte Stellen in seinem Code
aufmerksam gemacht - Stellen, über die er noch einmal nachdenken sollte. Geschieht das
immer wieder, hat es sogar einen Lerneffekt: Er wird im Lauf der
Zeit derartige, potentiell problematische Konstruktionen vermeiden.
Beliebt ist Lint nicht
Nein, dieses Programm wird nicht geliebt. Erstaunlich, wo es doch so ausgesprochen hilfreich sein kann? Trotzdem stimmt es es liegt einerseits an der Sprache C und andererseits daran, daß ein sinnvoller Umgang mit PC-Lint eine gewisse Erfahrung erfordert.
Das grundlegende Prinzip der Sprache C ist: "Es ist alles erlaubt, was nicht verboten ist" und in C ist nur wenig verboten, denn das Credo der "Erfinder" von C war "Trust the Programmer". Wenn vieles erlaubt ist, führt das zu einem saloppen Umgang - wie im wirklichen Leben auch. Das hat zur Konsequenz, daß praktisch jedes existierende C Programm Konstruktionen enthält, die potentiell unsauber sind, d.h. unter Umständen ein Problem beinhalten können. Lint weist nun den Entwickler auf alle diese Stellen hin das ist schließlich seine Aufgabe mit dem Ergebnis, daß es i.d.R. eine Vielzahl von Meldungen produziert (ein einfaches Beispiel).
Der Entwickler muß nun jede einzelne dieser Meldungen überprüfen: Handelt es sich hier um einen potentiellen Fehler oder ist die betreffende Stelle im aktuellen Kontext unkritisch? Verfügt er nun nicht über eine vernünftige Strategie im Umgang mit Lint, dann wird er die gleichen Meldungen noch weitere Male sehen jedes Mal, wenn er zu einem späteren Zeitpunkt seinen Quell-Code wieder untersuchen läßt.
Das ist es, was nach meiner Erfahrung das Arbeiten mit PC-Lint für viele Entwickler so unerfreulich macht: Sie setzen es erst dann ein, wenn ein Problem auftaucht, dessen Lösung sie anders nicht finden. Dann werden sie allerdings von einer Flut von Meldungen regelrecht erschlagen. Daraufhin legen sie es schnell wieder beiseite, bis eine erneute Katastrophe sie zwingt, es wieder einzusetzen. Auf diese Art und Weise werden sie leider nie eine sinnvolle Strategie entwickeln, wie sie PC-Lint in ihre Arbeit integrieren können.
Aber es ist natürlich möglich, effektiv mit PC-Lint umzugehen:
Im Handbuch gibt es dazu ein eigenes Kapitel: "Living with Lint" und
Sie finden hier in einem Artikel Hinweise zu einem sinnvollen Umgang mit PC-Lint.
Wenn Software-Qualität für Sie ein Thema ist, kommen Sie an PC-Lint nicht vorbei. Allerdings wird es vermutlich nicht ausreichen, Ihren Software-Entwicklern das Programm lediglich zur Verfügung zu stellen: es könnte sein, daß es im Schrank verschwindet. Wenn Sie jedoch den Einsatz von PC-Lint in Ihre allgemeine Strategie der Software-Qualitätssicherung integrieren, dann können Sie mit vergleichsweise geringem Aufwand ganz erhebliche Verbesserungen erreichen.
Sorgen Sie dafür, daß PC-Lint regelmäßig
eingesetzt wird es gibt keine andere Einzelmaßnahme, die eine vergleichbare
Steigerung der Produktivität Ihrer Software-Entwicklung ermöglicht.
Warum auch die 100 Warnungen, die Ihr Compiler liefern kann, Lint nicht ersetzen.
Beispiele, die Sie verblüffen werden: allgemeine für C, spezielle für C++ und ausgesuchte, die besonders für Entwickler von Embedded Systems von Interesse sein werden.
Weitere Beispiele (unkommentiert) beim Hersteller von PC-Lint
Nicht (zu) lange warten beim Einsatz von LintIn der Initialisierungs-Routine meines Programms wurden zentrale Variablen in Abhängigkeit der aktuellen Rahmenbedingungen initialisiert in einer ähnlichen Struktur wie in dem obigen Beispiel, nur etwas komplexer. Bei einer bestimmten - seltenen - Konstellation dieser Bedingungen wurde nun allerdings eine Variable vergessen: sie behielt ihren Anfangswert von '0'. Leider war diese Variable ein sog. File Handle, ein Zeiger. Wurde im Verlauf des Programms in das betreffende File geschrieben, dann wurde Speicher ab Adresse '0' überschrieben. Unter MS DOS war das ein tödlicher Fehler, denn dort lagen die Interrupt-Vektoren. Wurden sie das nächste Mal aktiviert, zeigten sie ins Nirwana und der Rechner stürzte ab. Das bedeutete u.a., daß nach jedem Testlauf der Rechner neu gebootet werden mußte - was den zeitlichen Aufwand noch einmal drastisch erhöhte. In einer bestimmten Phase meines Projekts zeigte sich dieser Fehler: An wechselnden, nicht näher zu bestimmenden Stellen stürzte mein Programm ab. Nach zwei Tagen intensiver Fehlersuche war ich noch nicht einen Schritt weiter gekommen. Es war eine der Situationen, in denen Software-Entwickler Albträume und Magengeschwüre bekommen:
Manchmal ist es ausgesprochen schwierig, aus dem Problem (Absturz des Rechners) auch nur die direkte Ursache abzuleiten (Interrupt-Vektoren zerstört) ganz zu schweigen von der indirekten Ursache, dem eigentlichen Fehler (fehlende Initialisierung). Entwickler von Embedded Systems aber nicht nur diese werden diese Erfahrungen kennen. Meine Geschichte kam letztlich doch noch zu einem guten Ende: Mir fiel ein, daß es dieses Programm PC-Lint gab und daß wir es sogar im Hause hatten. Ich erhielt prompt die obige Meldung "Variable 'xxx' may not have been initialized", und damit war das Problem auch schon gelöst. Vielleicht können Sie sich vorstellen, wie sehr ich mich danach über mich selber geärgert habe. Nein, nicht über den Fehler so etwas kann immer passieren sondern darüber, PC-Lint nicht schon nach der ersten Stunde fruchtloser Fehlersuche eingesetzt zu haben (zurück zum Text).
|
Eine typische Meldung von Lint, die auf ein mögliches Problem hinweistAngenommen, Sie haben eine sog. Integer-Variable iVal (das ist eine, die nur ganzzahlige Werte aufnehmen kann), und eine Gleitkomma-Variable gVal (zur Bearbeitung von Dezimalzahlen). Dann ist int iVal;
float gVal = 3.14;
iVal = gVal;
in C völlig legal (und auch üblich, weil mitunter notwendig). Ein potentielles Problem liegt nun darin, daß hier (mindestens) Genauigkeit verloren geht: die Nachkommastellen von gVal müssen abgeschnitten werden, um eine ganze Zahl zu erhalten. Aber da Gleitkomma-Variablen einen viel größeren Wertebereich abdecken als Interger-Variablen es tun, könnte sogar der Wert selbst völlig verfälscht werden, wenn nämlich gVal größer ist als der maximal darstellbare Integer-Wert. Also produziert Lint eine Meldung für diese Zuweisung: Möglicher Verlust an Genauigkeit, und der Entwickler muß an der betreffenden Stelle nachsehen und überprüfen, ob es sich um einen Fehler handelt oder nicht (zurück zum Text).
|
Copyright © Helmut Giese, email: hgiese@ratiosoft.com
Parkstr. 41, 34119 Kassel, Tel.: 0561 - 766 59 50, Fax: 0561 - 766 59 51
Königstor 59, 34119 Kassel, Tel.: 0561 - 739 35 30, Fax: 0561 - 739 35 31
Web Design von Bianca Engler: email
internet