Anbieter zum Thema
Die „Mängel“ in C lassen sich gut klassifizieren. Hier einige Beispiele, die jedem Programmierer sofort einleuchten:
Unspezifiziertes Verhalten in C:
- Die Repräsentation von Fließkomma-Datentypen.
- Die Reihenfolge, in der Ausdrücke (+, -, *, /, &, &&, …) ausgewertet werden.
- Die Reihenfolge und Kontinuität von Speicher, welcher durch die Funktionen calloc, malloc und realloc angefordert wurde.
- Ein Funktionspointer wird benutzt, um eine Funktion aufzurufen, die nicht mit der Deklaration der originalen Funktion kompatibel ist.
- Ein Funktionspointer wird in einen Pointer auf ein Objekt oder umgekehrt umgewandelt.
- Ein Bit-Feld ist mit einem anderen Typ definiert als int, signed int oder unsigned int.
- In den stdio-Funktionen existieren diverse undefinierte Verhaltensmuster.
Implementierungsabhängiges Verhalten in C:
- Bei einem „einfachen“ char kann nicht mit Bestimmtheit gesagt werden, ob dieser signed oder unsigned ist.
- Das Ergebnis einer Konvertierung eines int in einen kürzeren int oder das Ergebnis der Konvertierung eines unsigned int in einen signed int lässt sich nicht darstellen.
- Auf einen signed int wird eine bitweise Operation angewendet.
- Das Verhalten von calloc, malloc und realloc, wenn die angeforderte Speichergröße Null ist.
Warum MISRA-Regeln?
Die Frage ist, wenn es in C so viele unspezifizierte und unprüfbare Fälle geben kann, wie kann die Software trotzdem „sicherer“ werden? Natürlich lässt sich argumentieren, dass Profis um die kritischen Stellen wissen und damit umgehen können. Leider sind nicht alle Programmierer Profis. Daher gehen die MISRA-Regeln von Basis-Voraussetzungen aus und versuchen durch diverse empfohlene oder geforderte Einschränkungen unsichere Konstrukte in C von vornherein zu verhindern.
Im Folgenden einige Beispiele von häufigen Fehlerquellen in C:
- Programmierer machen Fehler: Vertipper (z. B. „=“ statt „==“ in einer if-Anweisung) oder der zu implementierende Algorithmus wurde falsch interpretiert.
- Der Programmierer versteht die Sprache falsch (z. B. die Rangfolge von Operatoren).
- Der Compiler erzeugt Code anders, als vom Programmierer erwartet. Nicht alle Features sind eindeutig definiert und können sich von Compiler zu Compiler unterscheiden.
- Der Compiler selbst enthält Fehler: Compiler und Linker sind ebenfalls nur Software. Sie halten nicht immer den Sprach-Standard ein. Die Compiler-Programmierer können Standard falsch interpretiert haben.
- Laufzeit-Fehler wie: Arithmetische Fehler (z. B. Division durch Null), Über- und Unterläufe, Gültigkeit von Pointer-Adressen, Fehler bei Array-Grenzen.
Regeln gemäß MISRA-C-2004
Die MISRA ist eine US-amerikanische Vereinigung von Herstellern, Zulieferern und Beratern aus dem Bereich der Automobilindustrie, welche Richtlinien zur Entwicklung und zum Einsatz sicherheitskritischer Software entwickelt. Darunter ist die Richtlinie MISRA-C eine der bekanntesten und wichtigsten im Bereich Embedded-Systeme.
Das Werk beinhaltet 141 Regeln insgesamt. Einige der Regeln sind nicht zwingend; ihre Befolgung wird jedoch empfohlen. Die Regeln sind in 21 Kategorien unterteilt. Hier einige Beispiele:
- Regel 14: Der Typ char sollte immer als signed char oder unsigned char deklariert werden. Der Datentyp char wird in Abhängigkeit vom Compiler entweder als signed oder als unsigned interpretiert.
- Regel 70: Funktionen sollten nicht sich selbst aufrufen (sowohl direkt, als auch indirekt).
- Regel 104: Nicht-konstante Pointer zu Funktionen sollten nicht verwendet werden.
- Regel 118: Dynamische Speicheranforderung (calloc, malloc, realloc, free) sollte nicht verwendet werden.
Der große Vorteil von MISRA ist, dass es Tools gibt, die die Einhaltung der meisten Regeln im Code prüfen und Hinweise ausgeben. Während Softwarestruktur, Konventionen und andere Empfehlungen meist nur auf „Good-Will-“ oder Review-Basis funktionieren, können diese Regeln durch toolbasierte Tests geprüft werden. Weiterführend gibt es die MISRA 2008, die nochmals das Regelwerk erweitert.
Sollte MISRA als Einschränkung zu C in Ihrem Unternehmen neu eingeführt werden, sprechen Sie vorher mit Ihren Entwicklern. Nicht alle Regeln sind unumstritten und bei Programmierern beliebt. Kompromisse können von Fall zu Fall durchaus erlaubt sein.
Quellen:
DIN EN 61508 Funktionale Sicherheit sicherheitsbezogener elektrischer, elektronischer, programmierbar elektronischer Systeme, Teil 1-7, November 2002
Sicherheitstechnik für Komponenten und Systeme, Peter Wratil, Michael Kieviet, Hüthig Verlag 2007
Elektronische Sicherheitssysteme, Josef Börcsök, Hüthig Verlag 2004
Functonal Safety, A Straightforward Guide to IEC 61508 and Related Standard,
David J Smith & Kenneth G L Simpson, Butterworth/Heinemann Verlag 2001
Software Criticality Analysis, TÜV Süddeutschland, H.Spiess, 2000
Einführung zur IEC61508, TÜV Süddeutschland, TÜV Automotive GmbH, 2003
IEC 61508- Teil 3; Sicherheitsgerichtete Softwareentwicklung, Olaf Winne, Design&Elektronik Forum „Sichere System“, 2004
Modeling for Reliability Analysis, Jan Pukite und Paul Pukite, IEEE Press 1998
Herleitung und Nachweis der SIL-3 Klassifizierung nach der Norm IEC61508-2 für ein zweikanaliges Mikrocontrollersystem, HTWK Leipzig, Quategra Gmbh; Jens Kleemann, 2008
Safer C, Les Hatton, Mcgraw-Hill Publ.Comp.,März 1995
(ID:317511)