Abstract

adesso Blog

Eingebettete Systeme werden häufig in sicherheitskritischen Bereichen wie Luftfahrt, Medizin und Automobiltechnik eingesetzt. Die Norm IEC 61508-7 gibt hierzu Empfehlungen für Programmiersprachen, die bei Nutzung einer definierten Teilmenge, Programmierrichtlinien und statischen Analysewerkzeugen bis zu SIL4 als 'besonders empfohlen' gelten. Dazu zählen auch C und C++. Allerdings ist die Wahl der Programmiersprache nicht selbsterklärend. Was kann den Entscheidungsprozess beeinflussen?

C oder C++?

Die Programmiersprache C wird seit Jahrzehnten in eingebetteten Systemen genutzt, da sie direkte Hardware-Kontrolle und effiziente Ressourcennutzung ermöglicht. Sie ist ideal für Systeme mit begrenzten Ressourcen und unterstützt durch ihre klare Sprachstruktur deterministische Reaktionen sowie eine präzise Kontrolle über Programmfluss und Ressourcen. Ein Nachteil von C ist die geringe Abstraktion, die fehleranfälligen Code begünstigen kann. Implizite Typumwandlungen und unklare Datentypdefinitionen können zu unerwartetem Verhalten führen, weshalb die Nutzung von C ein hohes Mass an Disziplin und Sorgfalt erfordert.

Die Programmiersprache C++ erweitert C um Funktionen wie objektorientierte Programmierung, Templates und Standardbibliotheken, was die Code-Strukturierung und Wartbarkeit verbessert. Die Komplexität von C++ bringt jedoch Herausforderungen mit sich. Performanceeinbussen können durch Mechanismen wie Ausnahmebehandlung oder dynamische Speicherverwaltung entstehen. Zudem erhöhen unsichere oder nicht-standardisierte Bibliotheken das Risiko von Sicherheitslücken.

Normen und Einschränkungen für Programmiersprachen, Tools und Bibliotheken

Es gibt zahlreiche Tools und Best Practices, die die Wartbarkeit und Qualität des Codes von C und C++ in sicherheitskritischen Systemen verbessern. Dazu zählen statische Analysetools, Unittests und Codereviews, die Sicherheitslücken, Programmierfehler und Verstösse gegen Codierstandards erkennen. Besondere Normen wie IEC 61508 oder MISRA beeinflussen massgeblich die Wahl der Programmiersprachen, Tools und Bibliotheken, da sie spezifische Anforderungen an die Entwicklungsmethodik, die Verifikation und die Validierung von Software stellen.

Einschränkungen durch Normen

  • IEC 61508 und MISRA: die Normen fordern die Nutzung von Programmierrichtlinien wie MISRA C oder MISRA C++, die den Einsatz bestimmter Sprachfeatures regeln. Beispielsweise schränken diese Richtlinien die Verwendung von C++-Templates, dynamischer Speicherverwaltung und Mehrdeutigkeiten in der Syntax ein, da diese schwer überprüfbar und potenziell fehleranfällig sind. Stattdessen wird die Nutzung von deterministischen und leicht nachvollziehbaren Konstrukten empfohlen.
  • Werkzeugqualifikation: gemäss IEC 61508 müssen Tools, die in sicherheitskritischen Systemen eingesetzt werden, qualifiziert sein. Das bedeutet, dass die Tools nachweislich keine zusätzlichen Risiken für die Softwarequalität einführen dürfen. Zertifizierte Compiler und statische Analysetools sind hier besonders hilfreich.
  • Modellbasierte Entwicklung: für Systeme, die auf modellbasierte Entwicklung setzen, gibt es zusätzliche Anforderungen, z. B. durch MISRA AC oder spezifische Styleguides für automatische Codegenerierung. Diese Richtlinien können sowohl auf der Modellierungsebene als auch auf der Ebene des generierten Codes angewendet werden.

Auswirkungen auf die Auswahl von Tools und Bibliotheken

  • Programmiertools: die Wahl geeigneter Entwicklungsumgebungen und Compiler ist entscheidend. Zertifizierte Compiler, die den Anforderungen der Normen entsprechen, reduzieren das Risiko unerwünschter Nebeneffekte. Beispiel: Compiler mit aktivierten Sicherheitschecks oder solche, die spezifische MISRA-Checks unterstützen.
  • Bibliotheken: die Verwendung von Standardbibliotheken (insbesondere in C++) wird oft eingeschränkt, da viele Funktionen (z. B. aus der Standard Template Library, STL) dynamische Speicherallokation oder andere schwer kontrollierbare Mechanismen verwenden. Stattdessen wird empfohlen, speziell für sicherheitskritische Anwendungen entwickelte Bibliotheken einzusetzen.
  • Codegenerierung: für automatische Codegenerierung aus Modellen müssen die eingesetzten Tools ebenfalls strengen Anforderungen entsprechen und nachvollziehbare, konforme Ergebnisse liefern.

Spezifische Einschränkungen für C++-Features

  • Templates: während Templates in C++ eine mächtige Möglichkeit zur Generierung von generischem Code bieten, sind sie in sicherheitskritischen Anwendungen oft eingeschränkt. Der Grund liegt in der Schwierigkeit, den generierten Code vollständig zu analysieren und zu testen, sowie in der potenziellen Erhöhung der Codekomplexität.
  • Dynamische Speicherverwaltung: C++-Features wie „new“ und „delete“ oder Smart Pointers werden oft kritisch gesehen, da sie Speicherlecks oder Fragmentierung verursachen können. Normen wie ISO 26262 empfehlen stattdessen die Verwendung von statischem oder Stack basiertem Speicher.
  • Mehrfachvererbung: obwohl C++ Mehrfachvererbung unterstützt, wird diese in sicherheitskritischen Projekten selten empfohlen, da sie die Codekomplexität erhöht und potenziell schwer nachvollziehbare Fehler einführen kann.

Interoperabilität und Laufzeitsicherheit in C und C++

Die Interoperabilität zwischen C und C++ ist aufgrund der engen Verwandtschaft der beiden Sprachen relativ einfach zu handhaben. Bestehende C-Module können in C++-Projekten ohne grossen Aufwand eingebunden werden, indem der C-Code in externe „C-Blöcke“ eingebettet wird, um Namensmangling zu vermeiden. Umgekehrt lassen sich viele C++-Funktionen und Klassen in C verwenden, solange sie keine spezifischen C++-Features wie Templates oder polymorphe Klassen nutzen. Dennoch sollte bei der Integration auf Unterschiede im Speicherlayout und auf abweichende Compiler-Implementierungen geachtet werden, um Kompatibilitätsprobleme zu vermeiden.

In Bezug auf Laufzeitsicherheit gibt es erhebliche Unterschiede zwischen C und C++. C bietet keine eingebauten Mechanismen zur Fehlervermeidung bei Laufzeitfehlern wie Nullzeigerzugriffen oder Pufferüberläufen. Entwickler:innen sind hier auf Disziplin und externe Tools angewiesen, um solche Fehler zu vermeiden. C++ bietet durch fortgeschrittene Sprachfeatures wie Exceptions und Standardbibliotheken wie std::vector und std::unique_ptr mehr Schutz vor typischen Laufzeitfehlern. Diese Mechanismen reduzieren die Wahrscheinlichkeit von Speicherlecks oder undefiniertem Verhalten. Jedoch kann die zusätzliche Komplexität von C++-Features wie Templates oder dynamischer Polymorphie selbst neue Fehlerquellen schaffen, die sorgfältig gehandhabt werden müssen, insbesondere in sicherheitskritischen Anwendungen.

Die Wahl der Programmiersprache hängt stark von den spezifischen Anforderungen des Projekts sowie der Expertise des Entwicklerteams ab.

In vielen Projekten kann die Kombination beider Sprachen eine effektive Lösung darstellen. Kritische hardwarenahe Funktionen können in C implementiert werden, um maximale Effizienz und Kontrolle zu gewährleisten. Gleichzeitig können komplexere, abstrahierte Module, in C++ entwickelt werden, um von dessen Strukturierungs- und Wartbarkeitsvorteilen zu profitieren. Diese hybride Herangehensweise erfordert jedoch klare Schnittstellendefinitionen und gut dokumentierte Programmierrichtlinien, um eine reibungslose Integration sicherzustellen.

Die Einhaltung von Normen beeinflusst die Auswahl von Programmiersprachen, Tools und Bibliotheken erheblich und fordert klare Einschränkungen bei der Verwendung bestimmter Sprachfeatures, insbesondere in C++.

Nach was für Kriterien erfolgt bei Euch die Auswahl der Programmiersprache in sicherheitskritischen Applikationen?

  • IoT & Embedded Systems: Innovation für die vernetzte Welt

    Erfahren Sie, wie adesso innovative IoT- und Embedded-Lösungen entwickelt, die Unternehmen helfen, ihre Produkte zu digitalisieren und zukunftssicher zu gestalten. Mehr erfahren

  • Embedded C – Effizienz und Präzision in der Softwareentwicklung

    Mit Embedded C bietet adesso massgeschneiderte Softwarelösungen für eingebettete Systeme, die höchsten Ansprüchen an Effizienz und Zuverlässigkeit gerecht werden. Entdecken Sie, wie wir Ihre Projekte mit modernsten Technologien und bewährten Methoden voranbringen. Mehr erfahren

  • Funktionale Sicherheit: Verlässlichkeit in sicherheitskritischen Systemen

    adesso unterstützt Unternehmen bei der Umsetzung funktionaler Sicherheit in Embedded- und IoT-Systemen. Mit umfassendem Know-how sorgen wir dafür, dass Ihre Produkte den höchsten Sicherheitsstandards entsprechen und regulatorische Anforderungen erfüllen. Mehr erfahren

  • Success Story Bühler: Digitale Transformation in der Lebensmittelindustrie

    Lesen Sie, wie adesso die Bühler Group bei der Entwicklung innovativer digitaler Lösungen unterstützt, Prozesse optimiert und neue Massstäbe in der Lebensmittelindustrie gesetzt hat. Mehr erfahren

Bild Benno Barten

Autor Benno Barten

Benno Barten ist als Professional Software Ingenieur bei der adesso Schweiz tätig. In seinem Berufsleben konnte er schon viel Erfahrung im Bereich der Funktionalen Sicherheit und der Softwareentwicklung von eingebetteten Systemen sammeln und begleitete Entwicklung von der Konzeptionierung bis zum fertigen Produkt.

Kategorie:

Branchen

Schlagwörter:

Internet of Things (IoT)