Embedded Coding meistern: Bewährte Gewohnheiten für weniger Fehler und mehr Sicherheit
Im vergangenen Jahrzehnt ist eingebettete Software in einem typischen Fahrzeug von einigen hunderttausend auf über 100 Millionen Codezeilen angewachsen. Der Wechsel zu 32-Bit-Prozessoren und reichlich Speicher hat beispiellose Funktionalität ermöglicht – doch gleichzeitig das Risiko subtiler Fehler erhöht, die Sicherheit und Security bedrohen.
Um Schritt zu halten, müssen Entwickler einen systematischen Ansatz verfolgen, der Fehler verhindert, bevor sie in die Codebasis gelangen. Zwei Hauptfehlerkategorien verdienen besondere Aufmerksamkeit:
- Coding-Fehler – z. B. Array-Zugriffe außerhalb der Grenzen. Diese sind durch statische Analyse erkennbar.
- Anwendungsfehler – werden erst sichtbar, wenn das Verhalten der Software gegen ihre Anforderungen validiert wird.
Die Einführung eines rigorosen Coding-Standards wie MISRA C/C++, gekoppelt mit anforderungsgetriebenen Tests, bietet eine mächtige „Unze Prävention“. Diese Strategie reduziert Debugging-Zeit, strafft Zeitpläne und schützt letztlich den ROI.
Warum Prävention entscheidend ist
Menschliche Fehler sind unvermeidbar – Ingenieure hetzen, übersehen Details oder interpretieren komplexe Datenflüsse falsch. Wenn Software an Größe und Vernetzung zunimmt, können diese Patzer zu kritischen Ausfällen kaskadieren. Ein disziplinierter Coding-Standard hilft, viele dieser Fallen frühzeitig zu erkennen und zu beseitigen.
Im C/C++-Ökosystem gehen rund 80 % der Defekte auf den Missbrauch von nur 20 % der Sprache zurück. Durch das Verbieten oder Einschränken problematischer Konstrukte hebt ein Standard die Codequalität dramatisch an.
Betrachten Sie das undefinierte Verhalten beim Rechts-Shift einer vorzeichenbehafteten Ganzzahl: Je nach Compiler kann das Ergebnis abweichen und zu inkonsistentem Programmverhalten führen. Ebenso kann eine Funktion, die einen Ringpuffer liest, auf manchen Compilern Werte in unerwarteter Reihenfolge zurückgeben. Diese Nuancen verdeutlichen die Abbildungen unten.

Abbildung 1. Compiler-abhängiges Verhalten in C/C++-Konstrukten. Quelle: LDRA

Abbildung 2. Undefiniertes Verhalten im Ringpuffer-Beispiel. Quelle: LDRA
MISRA C/C++ nutzen
MISRA, 1998 erstmals für die Automobilindustrie veröffentlicht, bleibt der Goldstandard für eingebettetes C/C++. Es spezifiziert:
- Begründung jeder Regel mit detaillierten Ausnahmen.
- Klare Beispiele für undefiniertes, unspezifiziertes und implementationsdefiniertes Verhalten.
- Leitfaden, welche Regeln „entscheidbar“ (werkzeugprüfbar) und welche „unentscheidbar“ sind.
2016 wurde MISRA um Security-kritischen Code erweitert – 14 neue Direktiven kamen hinzu. So verbietet Direktive 4.14 explizit Konstrukte, die zu undefiniertem Verhalten führen können, und stärkt damit die Security-Posture.

Abbildung 3. MISRA-Leitfaden zu undefiniertem und unspezifiziertem Verhalten. Quelle: LDRA

Abbildung 4. Rolle von Direktive 4.14 bei der Verhinderung undefinierten Verhaltens. Quelle: LDRA
Vom Code zur Anwendung: Anforderungen und Tests
Selbst fehlerfreier Code kann scheitern, wenn er seinen Zweck nicht erfüllt. Rückverfolgbarkeit der Anforderungen und Unit-Tests sind essenziell, um zu verifizieren, dass die Software wie entworfen funktioniert.
Bidirektionale Rückverfolgbarkeit verknüpft jede Funktion mit ihrer Low-Level-Anforderung und den Systemzielen. Dieses Mapping deckt fehlende oder überflüssige Features früh auf.

Abbildung 5. Bidirektionale Rückverfolgbarkeit von der Funktion zur Systemanforderung. Quelle: LDRA
Sind Low-Level-Anforderungen definiert, ergeben sich Testfälle natürlich. Deren Ausführung – idealerweise mit automatisierten Unit-Test-Tools – bestätigt, dass der Code seinen Vertrag erfüllt.

Abbildung 9. Ergebnisse automatisierter Unit-Tests. Quelle: LDRA
Neue Coding-Gewohnheiten etablieren
Moderne eingebettete Entwicklung erfordert einen ganzheitlichen Ansatz:
- Einen bewährten Coding-Standard implementieren (MISRA, CERT etc.).
- Metriken tracken – Defektdichte, Code Coverage, Compliance-Raten.
- Anforderungsrückverfolgbarkeit und automatisierte Regressionstests durchsetzen.
Diese Praktiken liefern saubereren, wartbareren Code, vereinfachen Feature-Erweiterungen und senken langfristige Wartungskosten – Vorteile, die sowohl in sicherheitskritischen als auch in nicht-kritischen Domänen wirken.
Diese Gewohnheiten anzunehmen ist nicht optional, wer einen Wettbewerbsvorteil anstrebt. Der Unterschied zwischen einer Codebasis, die ständiges Feuerlöschen erfordert, und einer, die sich reibungslos weiterentwickelt, liegt oft nur in einem disziplinierten Prozess.
Originalartikel von EDN.
Eingebettet
- Text Strings: Eine verborgene Sicherheitslücke in eingebetteter Software
- SOAFEE: Cloud-native Architektur für softwaredefinierte Automobilplattformen
- Pixus stellt robuste 6U OpenVPX-Frontplatten mit verbesserter struktureller Integrität vor
- Kontron enthüllt COM HPC: Neuer High-Performance Embedded Computing Standard
- GE Digital stellt Predictive Asset Management Software vor: Shift von reaktiv zu proaktiv
- CMMS-Training meistern: Teams engagieren & Retention boostern
- Open-Source-Software im IoT absichern: Software-Risiken mindern
- Drei bewährte Schritte zur Absicherung Ihrer Software-Lieferkette
- Saelig stellt Impact-D 100AL vor: Leistungsstarker, kompakter Embedded PC mit 15 Jahren Lebensdauer & umfangreichem I/O
- DevOps nutzen, um Herausforderungen bei Embedded Software zu meistern