In meiner Argumentation in diesem Artikel ziehe ich mich vollkommen auf C++98 zurück. Dies hat zwei Gründe. Zum ersten wurden sowohl die MISRA C++ Richtlinien als auch der "Technical Report on C++ Performance" in den Jahren vor dem C++11-Standard geschrieben. Zum zweiten zeige ich dadurch, dass selbst klassisches C++ die Mythen rund um C++ widerlegen kann.
MISRA C++
Die aktuellen MISRA C++:2008 Richtlinien wurden von der Motor Industry Software Reliability Association formuliert. Sie lehnen sich an die MISRA C Richtlinien an, die bereits auf das Jahr 1998 zurückgehen. Ursprünglich von der Automobilindustrie entwickelt, sind insbesondere die MISRA C Richtlinien der Industriestandard bei der Umsetzung von sicherheitskritischer Software im Flugzeugbau, Militär und auch im Medizinbereich. In Anlehnung an die MISRA C Richtlinien beschreiben die MISRA C++ Richtlinien eine sichere Teilmenge von C++.
Diese Teilmenge besteht aus gut 200 Regeln, die als document, required oder advisory bezeichnet werden.
Document:
Müssen eingehalten werden
Abweichungen sind nicht erlaubt
Verlangen öfters explizite Dokumentation
Required:
Sollen eingehalten werden
Abweichungen müssen formal beantragt, begründet, geprüft und dokumentiert werden
Advisory:
Sollen eingehalten werden
Abweichungen müssen nicht formal beantragt, sollen aber dokumentiert werden
Diese Regeln umfassen die Sprache C++ samt ihrer Bibliotheken. Der Anschaulichkeit wegen, will ich ein paar Regeln aus MISRA C++ nennen.
Unnötige Konstrukte
Das Projekt soll keinen toten Code enthalten. (required)
Das Projekt soll keinen unbenutzten Variablen enthalten. (required)
Assembler Deklaration
Jede Verwendung von Assembler soll dokumentiert werden. (document)
Arithmetik
Die Verwendung von Fließkommazahlen-Arithmetik soll dokumentiert werden. (document)
Sprache
Der C++03 Standard (Anmerkung: Kleine technische Korrektur von C++98) soll verwendet werden. (required)
Kommentare
Keine C-Kommentare sollen verwendet werden. (required)
Keine Codebereiche sollen auskommentiert werden. (advisory)
Zeiger Konvertierung
NULL soll nicht als natürliche Zahl verwendet werden. (required)
Mehrere Basisklassen
Klassen sollen nicht von einer virtuellen Basisklasse abgeleitet sein. (advisory)
Virtuelle Funktionen
Jede virtuelle Funktion, die eine virtuelle Funktion überschreibt, sollte das Schlüsselwort virtual verwenden. (required)
Ausnahmebehandlung
Ausnahmen sollen nur für die Fehlerbehandlung verwendet werden. (document)
Templates
Alle teilweisen oder vollständigen Templatespezialisierungen sollen in der gleichen Datei wie das primäre (allgemeine) Template deklariert werden. (required)
Makro Ersetzungen
Der # und ## Operator soll nicht verwendet werden. (advisory)
Bibliothek
Die C-Bibliothek soll nicht verwendet werden. (required)
Alle Bibliothek-Code soll konform zu MISRA C++ sein.(document)
Welche Schlussfolgerungen lassen sich aus dem Auszug der MISRA C++ Regeln für den Einsatz von C++ in sicherheitskritischen Anwendungen ableiten? Weder wird ein Haupt-C++-Feature noch die Sprache C++ als ganzes ausgeschlossen.
MISRA C++ geht noch ein Schritt weiter und stellt heraus, warum die Bedeutung von C++ in sicherheitskritischen System immer weiter zunimmt (1.1 The use of C++ in critical systems) :
C++ gives good support for high-speed, low-level, input/output operations, which are essential to many embedded systems.
The increased complexity of applications make the use of a high-level language more appropriate than assembly language.
C++ compilers generate code with similar size and RAM requirements to those of C.
Ein bitterer Wermutstropfen bleibt aber: MISRA C++ basiert auf klassischem C++. Modernes C++ hat aber deutlich mehr zu bieten für Embedded-Systeme. Leider gibt das C++-Standardisierungskomitee eine Geschwindigkeit vor, der MISRA nicht folgen kann. Aus Diskussion auf Foren nehme ich aber an, dass MISRA versucht, dieses Loch zu schließen.
Technical Report on C++ performance
2006 verfasst die Working Group WG 21 den ISO/IEC TR 18015. Der Titel hört sich sehr sperrig an. Tatsächlich ist das Dokument die erste Quelle, wenn es darum geht, die Performanz von C++ zu analysieren. Diesen Aspekt bringt das Ziel des Dokuments (1 Scope) direkt auf den Punkt.
to give the reader a model of time and space overheads implied by use of various C++ language and library features,
to debunk widespread myths about performance problems,
to present techniques for use of C++ in applications where performance matters, and
to present techniques for implementing C++ Standard language and library facilties to yield efficient code.
Verfasser des gut 200-seitigen Reports sind so bekannten Namen wie Dave Abrahams, Howard Hinnand, Dietmar Kühl, Dan Saks, Bill Seymour, Bjarne Stroustrup und Detlef Vollmann.
In dem Dokument selbst geht es um die C++ Sprachmerkmale, deren Overhead und Verwendung, dem Erzeugen von effizienten Bibliotheken in C++, der Nutzung von C++ in Embedded-Systemen und einer Schnittstelle in C++ um mit Hardware zu kommunizieren. Insbesondere auf die C++ Sprachmerkmale, deren Overhead und Verwendung, will ich genauer eingehen.
C++ Sprachmerkmale, Overhead und Verwendung
Bei ihrer Analyse greifen die Autoren auf drei Computerarchitekturen mit fünf verschiedenen C++ Compilern zurück. Die Compiler rufen sie mit unterschiedlichen Optimierungsoptionen auf. Die Ergebnisse, die ich deutlich vereinfachend darstelle, sind sehr aufschlussreich.
Namensräume
Besitzen keinen signifikanten Einfluss auf die Größe des Programms oder sein Zeitverhalten
Typkonvertierungs-Operatoren
Die C++-Casts const_cast, static_cast und reinterpret_cast unterscheiden sich weder in Größe noch Zeitverhalten von ihrem C-Pendant
Der zur Laufzeit ausgeführte dynamic_cast besitzt einigen (some) Overhead. (Anmerkung: Diese Konvertierung besitzt kein Pendant in C.)
Vererbung
Klasse
Eine Klasse (class) ohne virtuelle Funktionen ist genauso groß wie eine Struktur (struct).
Eine Klasse mit virtuellen Funktionen besitzt den Overhead eines Zeigers und einer virtuellen Funktionstabelle (virtual function table). Dies sind typischerweise 2 bis 4 Byte.
Funktionsaufrufe auf Objekten
Der Aufruf einer nicht-virtuellen, nicht-statischen, nicht-inline Funktion ist genauso teuer wie der Aufruf einer freien Funktion.
Der Aufruf einer virtuellen Funktion ist so teuer, wie der Aufruf einer freien Funktion mithilfe eines Zeigers, der in einem Array gespeichert ist.
Virtuelle Funktionen eines Klasse-Templates können Größenoverhead verursachen. (Anmerkung: Funktionen, die nicht vom Template-Parameter abhängen, sollten in eine Basisklasse alle Klassen-Templates extrahiert werden. Damit steht der Template-Parameter unabhängig Code allen abgeleiteten Klassen-Templates zur Verfügung.)
Das inlining von Funktionen bringt einen signifikanten Vorteil, reicht aber noch nicht ganz an die Performanz von C-Makros heran.
Mehrfachvererbung
Kann Zeit und/oder Größen Overhead implizieren.
Virtuelle Basisklassen besitzen gegenüber nicht-virtuellen Basisklassen zusätzlichen Overhead.
Run-Time Type Information (RTTI)
Pro Klasse werden typischerweise zusätzlich 40 Bytes benötigt.
Der typeid-Aufruf ist relativ langsam. Dies scheint aber ein Problem der Güte der Implementierung zu sein.
Die Konvertierung zur Laufzeit mit dynamic_cast ist langsam. Der Grund scheint laut dem Report vor allem auch in der Qualität der Implementierung zu liegen.
Ausnahmebehandlung
Zwei Strategien für den Umgang mit Ausnahmen haben sich etabliert.Das ist die Code- und die Table-Strategie. Während bei der Code-Strategie zur Laufzeit zusätzliche Datenstrukturen für den Ausführungskontext gemanagt und verschoben werden müssen, wird bei der Table-Strategie der Ausführungskontext in einer Tabelle vorgehalten.
Die Code-Strategie besitzt ein Größenoverhead für den Stack und die Laufzeit. Der Zeitoverhead ist ca. 6 Prozent, selbst wenn die Ausnahme nicht auftritt.
Die Table-Strategie besitzt weder Overhead in der Programmgröße noch in der Laufzeit (Anmerkung: Für die Laufzeit gilt dies nur, wenn keine Ausnahme auftrat). Dafür ist diese Strategie schwieriger zu implementieren.
Templates
Für jedes Template-Argument wird ein neues Funktions- oder Klassen-Template erzeugt. Naiver Umgang mit Templates kann daher zu einem deutlichen Anstieg der Codegröße führen. Moderne C++-Compiler können die Anzahl der Template-Instanziierung deutlich reduzieren. In der Standard Template Library wird teilweise oder vollständige Template-Spezialisierung angewandt, um die Anzahl der Template-Instanziierungen zu reduzieren.
Die genauen Details, die exakten Zahlen und alle weiteren Punkte lassen sich in dem Report TR18015.pdf schön nachlesen.
Das Vermitteln von Wissen zu modernem C++ ist Rainer Grimm eine Herzensangelegenheit.
(Bild: Rainer Grimm, Modernes C++)
Einen Wermutstropfen gibt es aber auch zu dem Technical Report on C++ Performance. Dieser Report ist von 2006. Insbesondere mit C++11 erhielt C+ viele Features, die es erlauben, höher optimierten Code zu schreiben. Daher fragte ich Detlef Vollmann, einen Mitautor des Reports, auf dem Meeting C++, ob sie nicht den Report auf modernes C++ aktualisieren wollen. Seine Nachfrage bei Bjarne Stroustrup ergab aber, dass er keine Zeit habe. Verständlich, aber dennoch ein bitterer Wermutstropfen.
Es ist für uns eine Selbstverständlichkeit, dass wir verantwortungsvoll mit Ihren personenbezogenen Daten umgehen. Sofern wir personenbezogene Daten von Ihnen erheben, verarbeiten wir diese unter Beachtung der geltenden Datenschutzvorschriften. Detaillierte Informationen finden Sie in unserer Datenschutzerklärung.
Einwilligung in die Verwendung von Daten zu Werbezwecken
Ich bin damit einverstanden, dass die Vogel Communications Group GmbH & Co. KG, Max-Planckstr. 7-9, 97082 Würzburg einschließlich aller mit ihr im Sinne der §§ 15 ff. AktG verbundenen Unternehmen (im weiteren: Vogel Communications Group) meine E-Mail-Adresse für die Zusendung von redaktionellen Newslettern nutzt. Auflistungen der jeweils zugehörigen Unternehmen können hier abgerufen werden.
Der Newsletterinhalt erstreckt sich dabei auf Produkte und Dienstleistungen aller zuvor genannten Unternehmen, darunter beispielsweise Fachzeitschriften und Fachbücher, Veranstaltungen und Messen sowie veranstaltungsbezogene Produkte und Dienstleistungen, Print- und Digital-Mediaangebote und Services wie weitere (redaktionelle) Newsletter, Gewinnspiele, Lead-Kampagnen, Marktforschung im Online- und Offline-Bereich, fachspezifische Webportale und E-Learning-Angebote. Wenn auch meine persönliche Telefonnummer erhoben wurde, darf diese für die Unterbreitung von Angeboten der vorgenannten Produkte und Dienstleistungen der vorgenannten Unternehmen und Marktforschung genutzt werden.
Meine Einwilligung umfasst zudem die Verarbeitung meiner E-Mail-Adresse und Telefonnummer für den Datenabgleich zu Marketingzwecken mit ausgewählten Werbepartnern wie z.B. LinkedIN, Google und Meta. Hierfür darf die Vogel Communications Group die genannten Daten gehasht an Werbepartner übermitteln, die diese Daten dann nutzen, um feststellen zu können, ob ich ebenfalls Mitglied auf den besagten Werbepartnerportalen bin. Die Vogel Communications Group nutzt diese Funktion zu Zwecken des Retargeting (Upselling, Crossselling und Kundenbindung), der Generierung von sog. Lookalike Audiences zur Neukundengewinnung und als Ausschlussgrundlage für laufende Werbekampagnen. Weitere Informationen kann ich dem Abschnitt „Datenabgleich zu Marketingzwecken“ in der Datenschutzerklärung entnehmen.
Falls ich im Internet auf Portalen der Vogel Communications Group einschließlich deren mit ihr im Sinne der §§ 15 ff. AktG verbundenen Unternehmen geschützte Inhalte abrufe, muss ich mich mit weiteren Daten für den Zugang zu diesen Inhalten registrieren. Im Gegenzug für diesen gebührenlosen Zugang zu redaktionellen Inhalten dürfen meine Daten im Sinne dieser Einwilligung für die hier genannten Zwecke verwendet werden. Dies gilt nicht für den Datenabgleich zu Marketingzwecken.
Recht auf Widerruf
Mir ist bewusst, dass ich diese Einwilligung jederzeit für die Zukunft widerrufen kann. Durch meinen Widerruf wird die Rechtmäßigkeit der aufgrund meiner Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt. Um meinen Widerruf zu erklären, kann ich als eine Möglichkeit das unter https://contact.vogel.de abrufbare Kontaktformular nutzen. Sofern ich einzelne von mir abonnierte Newsletter nicht mehr erhalten möchte, kann ich darüber hinaus auch den am Ende eines Newsletters eingebundenen Abmeldelink anklicken. Weitere Informationen zu meinem Widerrufsrecht und dessen Ausübung sowie zu den Folgen meines Widerrufs finde ich in der Datenschutzerklärung, Abschnitt Redaktionelle Newsletter.
Treffen Sie die Experten der Branche in Sindelfingen
Europas Leitkongress für Embedded Software Professionals
Jedes Jahr im Dezember treffen sich über 1.200 Professionals, um sich über aktuelle Technologien und Methoden zu informieren, Trends zu diskutieren sowie die Weichen für die Zukunft zu stellen.
In 14 Seminaren, 95 Vorträgen und 3 Keynotes warten fachlich fundierte und praxisnahe Inhalte auf die Teilnehmer des ESE Kongress. Der Kongress ist die ideale Plattform, um sich über moderne Methoden des Software Engineering und den Stand der Technik zu informieren. Melden Sie sich an und werden Teil der Embedded-Software-Community.
* Rainer Grimm ist seit vielen Jahren als Softwarearchitekt, Team- und Schulungsleiter tätig. In seiner Freizeit schreibt er gerne Artikel zu den Programmiersprachen C++, Python und Haskell, spricht aber auch gerne auf Fachkonferenzen. Auf seinem Blog Modernes C++ (heise Developer) beschäftigt er sich intensiv mit seiner Leidenschaft C++. Seit 2016 steht er auf selbstständigen Beinen. Insbesondere das Vermitteln von Wissen zu modernem C++ ist ihm eine Herzensangelegenheit. Seine Bücher "C++11 für Programmierer", "C++" und "C++-Standardbibliothek" für die "kurz und gut"-Reihe sind beim Verlag O'Reilly erschienen. Seine englischsprachigen Werke "The C++ Standard Library", "Concurrency with Modern C++" und "C++20" sind in mehrere Sprachen übersetzt worden. Im April erscheint sein englischsprachiges Buch zu den "C++ Core Guidelines" bei Addison-Wesley.