Fakten

Auf die Mythen folgen die Fakten. Damit verlassen wir das Land der Halb- und Unwahrheiten rund um C++.

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.

facts

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++ sammt 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 unbenutzen Variablen enthalten. (required)
  • Assembler Deklaration
    • Jede Verwendung von Assembler soll dokumentiert werden. (document)
  • Artithmetik
    • 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 ein virtuellen Basisklasse abgeleitet sein. (advisory)
  • Virtuelle Funktionen
    • Jede virtuelle Funktion, die eine virtuelle Funktion überschreibt, sollte das Schlüsselwort virutal 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 Bibiotheks-Code soll konform zu MISRA C++ sein.(document)

     

Diese und alle weiteren Regeln lassen sich durch statische Codeanalyse-Werkzeuge verifizieren.

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 sprerrig 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 System 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 Opimisierungsoptionen auf. Die Ergebnisse, die ich deutlich vereinfachend darstelle, sind sehr aufschlußreich.

  • Namensräume
    • Besitzen keinen signifikaten 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 virutellen 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 mit Hilfe 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 gemanaged 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 %, 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.

Ein Wermutstropfen gibt es aber auch zu dem Technical Report on C++ Performance. Dieser Report ist von 2006. Insbesondere mit C++11 erhielt C+ viele Feature, die es erlauben, höher optimierteren Code zu schreiben. Daher fragte ich Detelf 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.

Im nächsten Artikel werde ich die mir die automatische Typableitung mit auto anschauen. Was hat auto mit sicherheitskritischen Systemen zu tun? Viel!

 

 

 

 

 

 

 

title page smalltitle page small Go to Leanpub/cpplibrary "What every professional C++ programmer should know about the C++ standard library".   Hole dir dein E-Book. Unterstütze meinen Blog.

 

Mentoring

Stay Informed about my Mentoring

 

Rezensionen

Tutorial

Besucher

Heute 2903

Gestern 2770

Woche 18455

Monat 64400

Insgesamt 3528706

Aktuell sind 544 Gäste und keine Mitglieder online

Kubik-Rubik Joomla! Extensions

Abonniere den Newsletter (+ pdf Päckchen)

Beiträge-Archiv

Sourcecode

Neuste Kommentare