Continuous Integration und statische Analyse von C und C++ Programmen für eingebettete Systeme (Projekt an der FH Dortmund)

Dieses Projekt wurde im Rahmen der hochschulinternen Lehrförderung an der Fachhochschule Dortmund durchgeführt.

Weshalb Continuous Integration?

In der industriellen Praxis ist der Einsatz von Continuous Integration (CI) ein etabliertes und weit verbreitetes Mittel zur Qualitätssicherung der entwickelten Software. In diesem Rahmen werden vielfältige Analyseschritte automatisiert durchgeführt. Diese reichen von der statischen Analyse bis zu dynamische Tests auf verschiedenen Systemebenen, auch der statische Nachweis von Codeeigenschaften oder ein Deployment auf das Produktivsystem kann dazugehören.

 

Zu den typischen Schritten und Zielen gehören:
  • Prüfung auf Einhaltung von Codierrichtlinien wie MISRA, Google Style Guide, JSF oder SEI CERT
  • Prüfung auf verbreitete Fehlermuster
  • Detektion von Anomalien im Datenfluss wie z.B. nicht initialisierte Variablen
  • Detektion von Anomalien im Kontrollfluss wie z.B. Sprünge aus Schleifen oder nicht erreichbarer Code
  • Erhebung von Software-Metriken als Qualitätsindikator; dazu werden Größe, Komplexität und Struktur untersucht mit Metriken wie z.B. LoC, Kommentardichte oder McCabe
  • Bestimmung von Fehlerdichten, Trendanalysen
Ein kleiner Teil dieser Analyseschritte kann bereits vom Compiler durchgeführt werden, während tiefer gehende oder projektspezifische Analysen von speziellen Tools übernommen werden. Mit Hilfe von Continuous Integration werden diese Schritte zu einem festen Bestandteil des Entwicklungsprozesses. Eine vollständige Automatisierung garantiert dabei hohe Effektivität und höchste Effizienz.

 

Continous Integration für eingebettete Systeme

Beim Einsatz einer typischen Continuous Integration Toolkette für eingebettete Systeme ergeben sich meist eine Reihe von Problemen:
  • Für die häufig verwendeten Programmiersprachen C und C++ ist die Auswahl an guten Analysewerkzeuge recht eingeschränkt, zudem sind diese meist nur kommerziell verfügbar und recht teuer. Insgesamt ist die Situation hier unübersichtlich.
  • Entwicklungs- und Zielsystem verwenden häufig unterschiedliche Prozessor-Architekturen, zudem sind die im Zielsystem vorhandenen Ressourcen häufig stark eingeschränkt. Dies macht den Einsatz von Cross-Toolchains erforderlich und erschwert das automatisierte Testen sehr.
  • Aufgrund der langen Historie und der vielfältigen, stark heterogenen Einsatzmöglichkeiten existieren für C und C++ viele Standards und Best Practices, die nicht immer miteinander harmonieren. Insbesondere die C++-Welt verändert sich seit dem Erscheinen von C++11 rasant.
Auf der anderen Seite macht eine Reihe von Faktoren den Einsatz einer CI-Toolkette im Umfeld eingebetteter Systeme besonders attraktiv:
  • Die Fehlersuche ist in eingebetteten Systemen aufgrund des Echtzeitverhaltens und beschränkter Debugging-Möglichkeiten häufig besonders aufwändig und teuer. Fehler schon im CI zu finden kann also Aufwand und Kosten sparen.
  • Die dominierenden Programmiersprachen C und C++ ermöglichen dem Programmierer die Entwicklung extrem effizienter Programme, halten aber auch besonders viele Fehlermöglichkeiten und Fallstricke bereit. Eine CI-Toolkette kann solche Fehler im Vorfeld entschärfen helfen.
  • Insbesondere die Programmiersprache C++ ist äußerst komplex, so dass es für ein Team sinnvoll ist, die Sprache auf eine bewährte und allgemein verständliche Untermenge einzuschränken. Eine CI-Toolkette hilft bei der konsequenten Umsetzung einer solchen Strategie.
  • Eingebettete Systeme werden häufig für ein reguliertes Umfeld entwickelt wie z. B. zum Einsatz in sicherheitskritischen Systemen. Dabei ist sowohl für eine Zulassung als auch für eine Abwehr eventueller späterer Haftungsansprüche ein Nachweis der Einhaltung von Qualitätsstandards notwendig. Diese können durch eine geeignete CI-Toolkette etabliert werden.

Einsatz in der Lehre

Im Projekt StaticCppEvaluator entsteht eine CI-Toolkette für die C und C++-Programmierung eingebetteter Systeme. Damit sollen die Studierenden beim Erlernen eines professionellen Programmierstils noch besser unterstützt werden.

 

In ihren Praktika, Studien- und Abschlussarbeiten verwenden die Studierenden zur Zeit ein Konfigurationsmanagementsystem wie Gitlab oder Atlassian Bitbucket, um ihren Code in einem zentralen Repository zu verwalten. Bei jeder Übertragung in das Repository soll der Code automatisch auf typische Schwächen analysiert und mit Hilfe von Metriken bewertet werden. Das Ergebnis soll den Studierenden in Form einer Übersicht präsentiert werden, von der aus die einzelnen gefundenen Mängel interaktiv im Detail analysiert werden können.

 

So wird den Studierenden wesentlich häufiger und zeitnäher Feedback gegeben, als dies im Rahmen der persönlichen Betreuung durch die Lehrenden möglich wäre. Die Studierenden werden beim Erlernen eines professionellen Programmierstils, der zu einem nachvollziehbaren, korrekten, wartbaren und wiederverwertbaren Programmcode führt, optimal unterstützt. Daneben können die Studierenden die manchmal abstrakten Lehrinhalte aus den Software Engineering Veranstaltungen besser einordnen und in der täglichen Praxis anwenden. Sie lernen eine moderne, in vielen industriellen Projekten verwendete Werkzeugkette kennen und diese routinemäßig einzusetzen.