MISRA-C

MISRA-C ist ein C-Programmierstandard aus der Automobilindustrie, der von der englischen MISRA (Motor Industry Software Reliability Association) erarbeitet wurde. Der MISRA-C-Programmierstandard definiert eine Untermenge des Sprachumfangs von C, d. h., er umfasst Richtlinien, die zu einer Qualitätssteigerung (insbesondere der Softwarequalitätsaspekte der Zuverlässigkeit und Wartbarkeit) in der Software-Entwicklung führen sollen.

Geschichte

Der erste MISRA-Standard für die Programmiersprache C "MISRA C" wurde ursprünglich 1998 definiert. Inzwischen sind weltweit über 7000 Exemplare im Umlauf.[1] Auch in anderen Branchen wird er für sicherheitskritische Produkte zunehmend eingesetzt, z. B. im Flugzeugbau, beim Militär, in der Medizin und im Schienenverkehr.

Der erste Standard (MISRA C:1998) umfasste 127 Regeln, davon 93 als Vorschrift (required) und 34 als Empfehlung (advisory). Die Ausgabe MISRA C:2004 umfasste 144 Regeln, davon 112 required, 29 advisory und 3 deprecated (veraltet, abgelehnt). Die beiden Ausgaben nehmen Bezug auf C89/C90, nicht auf die neueren C-Standards C99 (ISO/IEC9899:1999) oder C11 (ISO/IEC9899:2011). Die aktuelle Ausgabe MISRA-C:2012 (MISRA C Version 3) ist im März 2013 herausgekommen und unterstützt auch C99. Außerdem wurde sie im Hinblick auf Verständlichkeit umstrukturiert und inhaltlich verbessert.

Seit 2008 gibt es den MISRA-Standard für C++, MISRA-C++:2008.

Ziele des Standards

Ziel der MISRA-Regeln ist es, Programme so sicher zu erstellen, dass sie auch in sicherheitskritischen Anwendungen zuverlässig laufen. Dazu gibt MISRA C vor allem Empfehlungen zu Sprachkonstrukten, die im C-Standard unklar spezifiziert sind, so dass der Hersteller des Compilers eine eigene Interpretation wählen muss, die von Compiler zu Compiler unterschiedlich sein kann und möglicherweise dazu führt, dass der gleiche Quelltext auf unterschiedlichen Compilern zu unterschiedlichen Programmen führt. MISRA-C enthält ebenfalls Regeln, welche die Lesbarkeit des Quelltextes verbessern und typische Fehler vermeiden sollen.

Wenn einzelne Regeln im Projekt oder einzelnen Modulen nicht angewendet werden sollen, so muss ein vorher definierter, formeller Prozess eingehalten werden, wobei die Abweichungen auch dokumentiert werden müssen. Andere MISRA-Veröffentlichungen beschäftigen sich mit weiteren Aspekten der Softwareentwicklung.

Compliance

MISRA-C-Compliance einer Codebasis bedeutet die Regelkonformität des Quellcodes eines Projekts zu den Richtlinien des MISRA-Standards. Um dies nachzuweisen ist eine "Compliance Matrix" erforderlich, also ein Dokument anhand dessen nachvollzogen werden kann, welche Richtlinie wo und wie geprüft wird (z. B. durch Compiler, statische Code-Analyse, Reviews, zusätzliche Projektdokumentation usw.). MISRA-C-Compliance ist nicht gleichbedeutend mit der blinden Einhaltung aller Regeln. Auch Abweichungen sind z. T. erlaubt. Dazu sind die MISRA-C-Richtlinien in drei Prioritäts-Kategorien unterteilt:

  1. mandatory“ Regeln müssen eingehalten werden. Abweichungen sind nicht erlaubt.
  2. required“ Regeln sollten eingehalten werden. Abweichungen müssen über einen formalen Abweichungsprozess beantragt, technisch begründet, geprüft und dokumentiert werden.
  3. advisory“ Regeln sollten eingehalten werden. Abweichungen müssen nicht formal beantragt werden, sollten aber dokumentiert werden.

Die Zuordnung zu den Prioritäts-Kategorien ist unterschiedlich für manuell implementierten C-Code und für C-Code, der mittels eines Codegenerators erzeugt wurde (siehe Anhang E "Applicability to automatically generated code"). Der technische Gesamtumfang der einzuhaltenden Richtlinien ändert sich daher nicht, sondern nur die geforderte Strenge diese einzuhalten.

Beispiele

Verschachtelte Kommentare

Kommentare können seit C99 sowohl mit // (Kommentar endet stets am Zeilenende) als auch mit /* eingeleitet und in einer beliebigen anderen Zeile mit */ beendet werden. Nach den MISRA-Regeln ist der Gebrauch von // jedoch nicht erlaubt.[2] Ebenso ist es nicht erlaubt, innerhalb eines /* */ Kommentarblockes ein weiteres Mal /* zu verwenden (verschachtelte Kommentare).[3]

In dem folgenden Beispiel würde die Funktion (meineFunktion()) nicht ausgeführt, da versehentlich ein Kommentarabschluss vergessen wurde. Deshalb sind eingebettete /* nicht erlaubt.

/* Kommentar, ohne Abschluss
<neue Seite>

meineFunktion();
/* Dieser Kommentar hat keine Bedeutung */

Will ein Programmierer diesen Abschnitt durch /* und */ deaktivieren, so kommt es auf den Compiler an, ob er bei Kommentaren die /* wie Klammern mitzählt, oder ob er nach dem ersten */ wieder Code erkennt und kompiliert:

/* Code testweise deaktivieren
// i um 1 erhöhen
i++
/* Wenn Zähler i gleich a ist, MeineFunktion aufrufen um einen hoch */
if (i==a) { meineFunktion(a) }
*/

Wenn der Compiler das erste */ als Ende des Kommentars versteht, dann wird die Zeile mit dem if kompiliert und später auch ausgeführt. Aus diesem Grunde sollte nicht mit geschachtelten Kommentaren gearbeitet werden.

Ergebnis von Zuweisungen

Die folgende Variante ist schlecht, weil man nicht nachvollziehen kann, ob der Programmierer einen Fehler gemacht hat, oder absichtlich dieses Konstrukt gewählt hat:

if ( i = a )
{
   /* Anweisung */
}

Der Compiler würde diese Variante erkennen und übersetzen zu:

/* Zuweisung                       */
i = a;
/* dann ein Vergleich              */
if ( i != 0 )
{
   /* Anweisung */
}

Möglicherweise meinte der Programmierer == und hat versehentlich = geschrieben, so dass die Anweisung nur bei Gleichheit von i und a ausgeführt werden soll:

if ( i == a )
{
   /* Anweisung */
}

Weitere Beispiele

Weitere Beispiele zu MISRA-C-Richtlinien sind:

  • Konstanten in einem vorzeichenlosen Kontext müssen mit einem U-Suffix versehen werden[4]
  • Variablen vom Typ float (Gleitkommazahlen) sollen nicht mit den Vergleichsoperatoren == oder != getestet werden[5]
  • goto soll nicht verwendet werden[6]
  • magic numbers vermeiden und stattdessen sinnvoll benannte Konstanten verwenden: #define MAXSIZE 12
  • Division durch null verhindern: if (b!=0) a/=b;[7]
  • Compilerunabhängigkeit sicherstellen, z. B. shiften neg. Zahlen: -3<<4 ==> -3*(1<<4)
  • Operatorrangfolgen sind nicht trivial, daher Klammern verwenden: (a && b || c) ==> ((a && b) || c)
  • Pointerarithmetik vermeiden und Feldgrenzen prüfen
  • Rekursion darf in keiner Form auftreten (weder indirekt noch direkt).
  • Umsetzung einer starken Typisierung[8]

Prüf-Werkzeuge

Bei der Programmierung von eingebetteten Systemen im automobilen Umfeld ist MISRA-C-konformer Code üblicherweise vorgeschrieben. Sofern der Compiler nicht optional die MISRA-Konformität überprüfen kann, werden zur Überprüfung Werkzeuge zur statischen Code-Analyse wie Axivion Suite[9], Astrée[10], Lint, QA-C/MISRA oder RuleChecker[11] verwendet.

Ein Hersteller für Werkzeuge zur automatischen Code-Generierung verweist darauf, dass einige Regeln von MISRA-C die Ausführungsgeschwindigkeit des Programms verringern können.[12]

Literatur

MISRA Veröffentlichungen können teilweise auch als PDF-Datei auf der Homepage erworben werden.

  • MISRA: MISRA-C:2004 - Guidelines for the use of the C language in critical systems, ISBN 0952415623 (PDF: 095241564X)
  • Johannes Heuft: Der Weg zurück zur Software-Produktivität, 2007, ISBN 978-3-937446-88-2 (Kapitel 5.2.4, S. 37–41: Kritik an MISRA-C und den anwendenden Qualitätssicherern)

Weblinks

Einzelnachweise

  1. http://www.misra.org.uk/
  2. MISRA 2004, Regel 2.2
  3. MISRA 2004, Regel 2.3
  4. MISRA 2004, Regel 10.6
  5. MISRA 2004, Regel 13.3
  6. MISRA 1998, Regel 56 und MISRA 2004, Regel 10.4
  7. MISRA 2004, Regel 21.1
  8. MISRA-C:2012 Rule 10.1 - 10.8
  9. Produktseite von Axivion. Axivion GmbH, abgerufen am 14. April 2020.
  10. Produktseite von Astrée. AbsInt Angewandte informatik GmbH, abgerufen am 24. November 2017.
  11. Produktseite von RuleChecker. AbsInt Angewandte Informatik GmbH, abgerufen am 24. November 2017.
  12. Artikel und Beispiele von dSpace, abgerufen am 29. Oktober 2011. (PDF; 78 kB) Abgerufen am 5. November 2011.