Statische Codeanalyse

Bugs und Defekte in Multitasking-Software eliminieren

22.01.2009 | Autor / Redakteur: David Kalinsky* / Martina Hafner

*Dr, David Kalinsky ist Leiter für Kundentrainings bei D. Kalinsky Associates Technical Training, USA und ein beliebter Dozent in USA, Europa und Israel. Kontakt: david@kalinskyassociates.com.
*Dr, David Kalinsky ist Leiter für Kundentrainings bei D. Kalinsky Associates Technical Training, USA und ein beliebter Dozent in USA, Europa und Israel. Kontakt: david@kalinskyassociates.com.

Dank einer neuen Generation statischer Analysetools lassen sich Multitasking-Fehler leichter aufspüren, die oft in Verbindung mit einem Echtzeitbetriebssystem auftreten und mit herkömmlichen Softwaretests nur schwer gefunden werden. Erst seit kurzem eignen sich diese Tools für das riesige Spektrum an Fehlern, die typischerweise in Echtzeit- Software auftreten, in denen es zu Interaktionen zwischen mehreren Tasks sowie mit einem RTOS kommt.

Vor etwa 30 Jahren, in meinem ersten Job im Bereich Echtzeitsysteme, leitete ich ein Softwareentwicklungsteam, das an einem Erste-Hilfe-Monitor arbeitete (das Gerät war etwa einen Kubikmeter groß, also nicht so kompakt wie die Monitore in modernen medizinischen Geräten, wie wir sie heute kennen). Eines Tages rief mich der Firmenchef zu sich und fragte mich: „David, warum schaffen Sie es nicht, dass Ihre Software auf Anhieb fehlerfrei läuft?“ Er fuhr verärgert fort: „Laut Ihren Berichten haben Sie die Software doch fertig gestellt, aber danach sind Sie noch monatelang damit beschäftigt, sie von sogenannten Bugs zu befreien. Können Sie die Software denn nicht einfach von Anfang an richtig programmieren? Sie würden sich eine Menge Frust und ich mir einen Haufen Geld sparen.“ Damals in den Siebzigern hatte ich noch keine Antwort auf diese Fragen. Ich dachte, dass er mich feuern würde und meine Karriere im Embedded-Bereich damit beendet sei.

Machen wir einen Zeitsprung in die Gegenwart. Dreißig Jahre sind inzwischen vergangen, und Embedded-Entwickler haben viel über Wirtschaftlichkeit und Management in der Softwareentwicklung gelernt. Trotzdem wird auch heute noch gut die Hälfte der Entwicklungszeit dafür aufgewendet, Fehler im Softwarecode zu finden und zu beheben.

Seit kurzem gibt es einen Hoffnungsschimmer am Horizont der Softwareentwicklung — eine neue Generation von Tools für die statische Codeanalyse. Diese analysieren Softwarecode auf Bugs und andere Defekte, ohne dass die Programme selbst ausgeführt werden müssen. Sie basieren auf bestehenden Analysatoren wie beispielsweise MISRA-C-Compilern und LINT und verwenden Algorithmen, die den Sourcecode akribisch auf Softwarefehler prüfen und gefundene Fehler zuverlässig und hochpräzise anzeigen.

Bild 1: Codedefekt, angezeigt von einem statischen Analysetool. Der statische Analysator meldet, dass ein Buffer zu klein ist.
Bild 1: Codedefekt, angezeigt von einem statischen Analysetool. Der statische Analysator meldet, dass ein Buffer zu klein ist.

Die Ausführungspfade durch die Codebasis werden voll automatisch überprüft. Dabei identifizieren die Tools komplexe Defekte sowie Fehler, die die Interaktion zwischen mehreren Prozeduren betreffen und über zahlreiche Sourcecode-Dateien verteilt sind.

Mit den neuesten Versionen dieser statischen Analysetools lassen sich sogar einige Multitaskingfehler aufspüren, die oft in Verbindung mit einem Echtzeitbetriebssystem (RTOS) auftreten. Mit herkömmlichen Softwaretests werden diese nur schwer gefunden, da sie selten und scheinbar sporadisch auftreten. Statische Analysetools jedoch ermöglichen die deterministische Identifikation solcher Bugs.

Ergänzendes zum Thema
 

RTOS-Spezialkurse mit Dr. David Kalinsky in Deutschland

Ergänzendes zum Thema
 

Expertenmeinung des Autors

Kriterien für die Codeabdeckung: Line und Path Coverage

Ein wichtiges Kriterium bei der Identifizierung und Beseitigung von Softwarefehlern ist die Codeabdeckung. Sie definiert, welcher Teil der Codebasis in welcher Tiefe untersucht wird, und lässt sich unterteilen in Line Coverage (Anweisungsabdeckung) und Path Coverage (Pfadabdeckung).Die Line Coverage misst den Anteil aller Codezeilen, die auf Defekte untersucht werden. In vielen Embedded-Projekten liegt das Ziel bei einer Line Coverage von 100%, was sich aufgrund technischer Einschränkungen jedoch häufig nicht vollständig umsetzen lässt. Doch selbst wenn 100% Line Coverage erreicht werden, ist noch längst nicht sichergestellt, dass alle Defekte im Code identifiziert werden. Hier ein Beispiel:

void npd_switcher(int cond) {

char * c = 0;

char d[] = “a”;

if (cond) {

c = d;

*c = ‘b’;

}

*c = ‘c’;

}

In diesem Beispiel wird über einen einzelnen Testfall, der npd_switcher(1); aufruft, jede Codezeile der Funktion ausgeführt. Es wird zwar eine Line Coverage von 100% erreicht, doch es befindet sich immer noch ein gravierender Fehler im Code. Wenn die Eingangsvariable cond den Wert 0 hat, versucht die letzte Zuweisungsanordnung in der Funktion, die Adresse 0 zu beschreiben; ein Null-Pointer-Zugriff ist jedoch nicht erwünscht. Trotz 100 Prozent Line Coverage bleibt ein grundlegender Fehler unentdeckt.

Die effektivere Methode der Abdeckung ist die Path Coverage. Sie misst den Anteil aller Pfade durch jede Funktion einer Applikation, die auf Fehler überprüft werden sollen. Stellen Sie sich vor, Sie erzeugen einen Ablaufplan für eine Applikation, in dem jeder Entscheidungspunkt (if, while, switch, etc.) eine Verzweigung im Ablaufplan darstellt. Die obige Funktion npd_switcher(); hat zwei Pfade. Der erste Pfad nimmt bei if(cond) die Abzweigung TRUE und ist der gleiche Pfad, der für diesen Code 100% Path Coverage erzielt hat. Der zweite Pfad folgt bei if(cond) der Abzweigung FALSE. Es ist ein realer Pfad, auch wenn es für die ELSE-Bedingung keinen Code gibt. Tatsächlich ist dieser zweite Pfad derjenige, der den vorher unentdeckten Null-Pointer-Zugriff enthält.

Wenn nun die Path-Coverage-Methode so effizient ist, warum kommt sie dann nicht immer zum Einsatz? Die Antwort ist einfach: Die technische Umsetzung ist nahezu unmöglich, und der Arbeitsaufwand wäre unglaublich hoch. Die Anzahl von Pfaden in einer Softwarefunktion kann exponentiell zu der Anzahl an Zuständen und Entscheidungen im Code ansteigen. Schleifen können zu einer sehr großen Anzahl von Pfaden führen.

Um die Path Coverage Methode effektiv einzusetzen, muss man also die Anzahl der zu überprüfenden Pfade begrenzen. Nehmen wir als Beispiel die Norm DO-178B Level „A“ – der höchste Level, bei dem ein Softwareausfall in einem sich in der Luft befindlichen Flugzeug katastrophale Folgen hätte. Diese Norm fordert bei Software für Luftfahrtanwendungen den Abdeckungsgrad „Modified Condition/Decision Coverage“ (MC/DC). Im Wesentlichen besagt dies, dass an jeder Abzweigung in der Software jeder Zustand und jede Entscheidung auszuführen sind und damit mindestens einmal jeden möglichen Wert annehmen.

Inhalt des Artikels:

Kommentar zu diesem Artikel abgeben

Schreiben Sie uns hier Ihre Meinung ...
(nicht registrierter User)

Kommentar abschicken
copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Infos finden Sie unter www.mycontentfactory.de (ID: 285126 / Software-Implementierung)