Entwickler haben in einigen Fällen Speicher freigemacht, der dann automatisch Variablen zum Gebrauch an anderer Stelle zugewiesen wurde. Das ist zwar legitime C-Syntax, birgt aber gewisse Gefahren. Die neue MISRA-Regel schützt die Entwickler hier gewissermaßen vor sich selbst, denn im vorliegenden Fall besagt die Regel, dass ein Speicherblock nur dann freigegeben werden darf, wenn er mit Hilfe einer standardmäßigen Bibliotheksfunktion zugewiesen wurde.
void fn ( void )
{
int32_t a;
free ( &a ); /* Non-compliant - a does not point to allocated storage */
}
MISRA C:2012 definiert Richtlinien entweder als notwendig, empfohlen oder - neu - als zwingend. Die eben erwähnte Speicherregel ist ein Beispiel für eine zwingend vorgeschriebene Regel, die unter keinen Umständen verletzt werden darf (Bild 3).
Erforderliche und empfohlene Richtlinien können im Vergleich dazu verletzt werden. Bei empfohlenen Regeln kann der Programmierer selbst entscheiden, ob er sie außer Acht lässt, während bei erforderlichen Regeln möglicherweise ein Vorgesetzter zu entscheiden hat.
Richtlinien begründen
Die bisherigen MISRA-Versionen gaben einfach die Verhaltensweise vor, ohne eine Begründung für die hinter den Regeln stehende Intention zu liefern. Die neue Version hingegen erläutert, weshalb die einzelnen Richtlinien sinnvoll sind. Zum Beispiel kommen typedefs anstelle von Basistypen für numerische Werte zum Einsatz, aus denen Größe und Vorzeichenbehaftung hervorgehen. So können in einer 32-bit-C90-Implementierung die folgenden Definitionen in Frage kommen:
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef signed long int64_t;
Die Begründung verhindert eine mögliche irrige Annahme, die Einhaltung dieser Richtlinie garantiere die Portierbarkeit, weil die Größe des int-Typs darüber entscheiden kann, ob es bei einem Ausdruck zu einer int-Promotion kommt oder nicht. Beispielsweise erfolgt bei einem Ausdruck des Typs int16_t keine Promotion, wenn int mit 16 bit implementiert wird, während es bei einer 32-bit-Implementierung zu einer Promotion kommt. In diesem Fall hilft die Begründung den Entwicklern also, einen gängigen Fallstrick zu umgehen.
Sprunganweisungen - ein notwendiges Übel?
Sehr häufig werden Sprunganweisungen genutzt, um Unklarheiten zu beseitigen oder unzureichend definierte Algorithmen nachzubessern. Dennoch gibt es Situationen, in denen sie gerechtfertigt sind. Wenn es zum Beispiel in einem Leit-Algorithmus zu einer Notsituation kommt, ist es besser, per Goto den direkten Weg zu wählen, denn es bleibt keine Zeit, ein Flag zu setzen, dessen Status erst später in der Schleife geprüft wird. Aus diesem Grund wurde die Regel „auf die Verwendung von Goto-Anweisungen ist zu verzichten“ von der Kategorie „erforderlich“ in die Kategorie „empfohlen“ verlegt. Außerdem grenzen zwei weitere Regeln die Umstände, unter denen Goto-Anweisungen akzeptabel sind, weiter ein:
Prüfung von automatisch generiertem Code Auch automatisch generierter Code, der in Automotive-Anwendungen häufig zum Einsatz kommt, wird von einem Software-Entwickler geschrieben, sei es in Form von Templates oder als manuell codierte „S“-Modelle. Die gesicherte Konformität eines generierten Codes zu einer Untermenge einer Sprache liefert die Bestätigung, dass es in der betreffenden manuellen Implementierung keine Fehler gibt, die die Qualität des automatisch generierten Quell-Codes beeinflussen. Die für automatisch generierten Code geltenden Regeln unterscheiden sich aus mehreren Gründen von denen, die sich auf manuell geschriebenes C beziehen. Zum Beispiel lassen sich Variablennamen in automatisch generiertem Code einsetzen, die für den Menschen nicht unterscheidbar, aber für den vorgesehenen Zweck hinreichend eindeutig sind.
Es gibt zudem Situationen, in denen automatisch generierter Code das Gegenteil von manuell geschriebenem Code tun soll. Zum Beispiel schreiben die MISRA-C-Regeln vor, dass eine Default-Anweisung immer in eine Case-Anweisung hineingeschrieben wird. Das entsprechende MISRA AC besteht auf dem Gegenteil, weil ein automatischer Code-Generator nicht entscheiden kann, welches die Default-Aktion ist. Die nötige Ergänzung zur Implementierung der Default-Aktion muss manuell hinzugefügt werden. Die MISRA-Sprachuntermengen ebnen Entwicklern den Weg, die Möglichkeiten der von ihnen gewählten Sprache in vollem Umfang zu nutzen, ohne die Funktionen einzuschränken.
MISRA C: 2012 - und was kommt danach?
MISRA C:2012 schafft eine ideale Grundlage für eine Sprach-Untermenge zum Einsatz in jeglichen sicherheitskritischen Applikationen des Automotive-Bereichs. ISO 26262 schreibt allerdings nicht exakt vor, welche Codierungs-Regeln anzuwenden sind. Gerüstet mit den passenden Werkzeugen, erhalten Entwicklungs-Teams die Flexibilität, das Regelwerk passgenau auf die Anforderungen eines bestimmten Projekts zuzuschneiden. Hierzu lassen sich entweder hauseigene Regeln hinzufügen oder es werden - eine entsprechende Rechtfertigung vorausgesetzt - bestimmte MISRA-Regeln außer Kraft gesetzt (Bild 4).
Einhaltung bewährter Codier-Verfahren
MISRA-geprüfter Code weist in der Regel wenige Defekte auf, lässt sich einfach pflegen und ist leicht lesbar, konsistent und verifizierbar. Im Wesentlichen geht es bei MISRA um bewährte Verfahrensweisen beim Codieren. Dieses Prinzip wird durch den Verweis auf die entsprechenden Codier-Regeln in ISO 26262 bekräftigt. MISRA-C:2012-Regeln helfen, den hohen Anforderungen an die Software-Qualitätssicherung gerecht zu werden. Testwerkzeuge mit Unterstützung für die MISRA-Kon-formität sollten die Möglichkeit geben, einfach zwischen verschiedenen Versionen des Standards (C, C++, Java) und der passenden Untermenge (MISRA C:2004 für frühere, MISRA C:2012 für neue Projekte sowie MISRA AC für automatisch generierten Code) zu wechseln. Außerdem kann der Anwender zwischen der vollständigen Konformität und einer anwenderdefinierten Untermenge der Regeln wählen, die hausinternen Vorlagen oder Anforderungen entsprechen.
Die Autoren
Chris Tapp |
---|
ist als Field Applications Engineer bei LDRA tätig. Er arbeitete nach dem Abschluss seines Studiums an der University of Durham im Jahr 1987 größtenteils als selbstständiger Berater für Industrieunternehmen der Automobil-, Steuerungs- und IT-Branche. Seit 2001 beschäftigt er sich mit MISRA und ist zur Zeit Vorsitzender der MISRA C++ Working Group sowie aktives Mitglied der MISRA C Working Group. Seit 2007 arbeitet Tapp bei LDRA und hat sich dort auf Programmierstandards spezialisiert. |
Mark Pitchford |
---|
wirkte als Entwickler und Manager an vielen bedeutenden industriellen und kommerziellen Projekten mit und arbeitete hierzu sowohl im Vereinigten Königreich als auch längere Zeit in Kanada und Australien. Seit 2001 auf den Bereich Software-Test spezialisiert, arbeitet er in ganz Europa und darüber hinaus als Field Applications Engineer für LDRA Ltd. |