Sichere C -Programmierung Fa. Evosoft N - PowerPoint PPT Presentation

1 / 35
About This Presentation
Title:

Sichere C -Programmierung Fa. Evosoft N

Description:

Sichere C++-Programmierung Fa. Evosoft N rnberg Zusammenfassung der vermittelten Programmierrichtlinien Performance von Exceptions Die Implementierung von Exceptions ... – PowerPoint PPT presentation

Number of Views:55
Avg rating:3.0/5.0
Slides: 36
Provided by: MCKu5
Category:

less

Transcript and Presenter's Notes

Title: Sichere C -Programmierung Fa. Evosoft N


1
Sichere C-ProgrammierungFa. Evosoft Nürnberg
  • Zusammenfassung der vermittelten
    Programmierrichtlinien

2
Const-Qualifizierung
  • Nutzen Sie die const-Qualifizierung
  • für Variablen, deren Wert allein durch die
    Initialisierung festgelegt wird und sich
    anschließend nicht mehr ändert
  • zur Unterscheidung von in- und
    inout-Parametern wenn Zeiger oder Referenzen
    übergeben wird
  • um Methoden zu markieren, welche für
    const-qualifizierte Objekt-Instanzen aufrufbar
    sein sollen

3
Zeiger vs. Referenzen
  • Nutzen Sie Referenzen,
  • wenn dadurch immer ein Objekt referenziert wird,
  • und es sich während der Lebensdauer der Referenz
    stets ein und dasselbe Objekt handelt
  • Nutzen Sie Zeiger
  • wenn auch der Sonderfall kein Objekt (
    Null-Zeiger) darstellbar sein muss
  • oder während der Lebensdauer des Zeigers
    unterschiedliche Objekte referenziert werden

4
Explizite Typumwandlung
  • Nutzen Sie static_cast für Umwandlungen
  • zwischen arithmetischen Datentypen, wenn der
    Zieltyp einen kleineren Wertebereich hat und mit
    dem Cast eine Warnung des Compilers vermieden
    wird
  • von Ganzzahlen in Gleitpunktzahlen, wenn ein
    Quotient mittels Gleitpunkt-Division berechnet
    werden soll
  • nur dann als Down-Cast in einer
    Vererbungslinie, wenn es sich um extrem
    zeitkritischen Code handelt und die zusätzliche
    Sicherheit eines dynamic_cast als absolut
    verzichtbar erscheint

5
Explizite Typumwandlungen
  • Nutzen Sie dynamic_cast
  • um Down-Casts in einer Vererbungslinie
    abzusichern
  • mit der Zeiger-Syntax, wenn sie den Fehlerfall
    mit explizitem Code behandelt wollen
  • in der Referenzsyntax, wenn Sie im Fehlerfall
    eine Exception auslösen möchten
  • Einschränkung
  • dynamic_cast funktioniert nur für Objekte von
    Klassen mit mindestens einer virtuellen Methode
  • machen Sie notfalls den Destruktor virtuell

6
Explizite Typumwandlungen
  • Sofern Ihr Klassen-Design nicht ohne Verwendung
    von const_cast auskommt
  • überprüfen Sie das Design auf mögliche
    Alternativen
  • verwenden Sie ggf. mutable (z.B. bei redundanten
    Attributen mit lazy evaluation)
  • Die Notwendigkeit zur Verwendung von
    reinterpret_cast
  • sollte sich auf hardware-nahen Code beschränken
    (z.B. Programmierung vom Embedded Devices oder
    Treibern)
  • kann in sehr generischem Code oft durch die
    Verwendung von Templates reduziert werden

7
Klassenspezifisch definierte Typumwandlungen
  • Konstruktoren mit genau einem Argument vom Typ T
  • werden ggf. automatisch zur Umwandlung des Typs T
    in die betreffende Klasse angewendet
  • um diese automatische Anwendung zu vermeiden
    können solche Konstruktoren als explicit markiert
    werden
  • Sogenannte Type-Cast-Methoden in der Syntax
    operator T()
  • werden ggf. automatisch zur Umwandlung der
    betreffenden Klasse in den Typ T angewendet
  • um diese automatische Anwendung zu vermeiden sind
    stattdessen Methoden der Art T to_T() zu
    verwenden

8
Vererbung und Komposition
  • Bei Vererbung wie bei Komposition
  • sind die Datenelemente einer Klasse als Teil in
    einer anderen Klasse enthalten
  • kann die enthaltene Klasse als Basis-Klasse
    angegeben werden
  • Bei Vererbung
  • muss die Basis-Klasse public sein
  • gilt das Liskovsche Ersetzungsprinzip
  • Bei Komposition
  • kann die Basisklasse private oder protected sein
  • kann statt einer Basisklasse auch ein Attribut
    entsprechenden Typs verwendet werden

9
Interfaces
  • Können als Bündel von Funktionszeigern
    verstanden werden
  • Bei der Definition von Interfaces
  • gibt es (anders als in Java) kein spezielles
    Konstrukt
  • sind Klassen mit ausschließlich rein virtuellen
    Methoden zu verwenden
  • Bei der Implementierung von Interfaces
  • werden diese als public-Basisklassen verwendet
  • gilt (genau wie in Java), dass eine einzelne
    Klasse auch mehrere Interfaces auf einmal
    implementieren kann

10
LSP Liskov Substituion Principle
  • Barbara Liskov formulierte folgendes
    Ersetzungsprinzip
  • Ein Objekt einer abgeleiteten Klasse muss überall
    dort akzeptabel sein, wo eine seiner Basisklassen
    erwartet wird.
  • In C ist das LSP i.d.R. zur Laufzeit ein
    No-Op, da die Attribute der Basisklasse am
    Anfang des Datenbereichs der abgeleiteten Klasse
    liegen
  • d.h. der this-Zeiger gilt unverändert für beide
    Objekte.
  • Das LSP gilt nicht in umgekehrter Richtung
  • d.h. Basisklassen werden niemals (automatisch)
    dort akzeptiert, wo eine abgeleitete Klasse
    erwartet wird
  • sondern erfordern ggf. stets eine explizite
    Typumwandlung (Down-Cast)
  • Auch dieser Down-Cast kann zur Laufzeit ein
    No-Op sein
  • außer im Fall von Mehrfachvererbung

11
Vererbung und Überschreiben von Methoden in
abgeleiteten Klassen
  • Vererbung kann als Erweiterung verstanden
    werden, denn eine abgeleitete Klasse kann
  • ihrer Basis-Klasse weitere Attribute hinzufügen
  • ihrer Basis-Klasse weitere Methoden hinzufügen
  • einer geerbten Methode weitere Anweisungen
    hinzufügen
  • Letzteres geht allerdings nur durch Überschreiben
    (overriding)
  • d.h. die abgeleitete Klasse ersetzt die geerbte
    Methode durch eine neue ...
  • ruft dort jedoch die Methode der Basisklasse
    auf und
  • kann jetzt davor und dahinter Anweisungen
    hinzufügen

12
LSP-Problematikbei Zeigern und Arrays
  • C hat von C den engen Zusammenhang zwischen
    Zeigern und Arrays übernommen
  • Zeiger auf Array-Elemente können inkrementiert
    werden
  • und zeigen dann auf das nächste Element
  • Es entspricht zumindest in C der üblichen Praxis,
    eine Schleife über alle Elemente eines Arrays mit
    Zeigern zu implementieren
  • Durch das LSP
  • kann ein Basisklassen-Zeiger jederzeit auf ein
    Element in einem Array von abgeleiteten Klassen
    verweisen
  • wird aber falsch inkrementiert, wenn die
    abgeleitete Klasse gegenüber der Basisklasse mehr
    Speicherplatz benötigt
  • Das Problem tritt oft etwas verschleiert in
    Erscheinung,
  • wenn ein Array als Parameter an eine Funktion
    übergeben wird
  • wobei technisch gesehen lediglich Zeiger
    verwendet werden

13
Vor- und Nachbedingungen(Pre- und
Post-Conditions)
  • Beim Überschreiben von Methoden ist das LSP zu
    beachten
  • Vorbedingungen dürfen niemals strenger gefasst
    sein als die der überschriebenen Methode
  • Nachbedingungen dürfen niemals schwächer gefasst
    sein als die der überschriebenen Methode
  • Andernfalls würde Code. der für die Basisklasse
    korrekt ist, mit der abgeleiteten Klasse nicht
    mehr funktionieren
  • Vor- und Nachbedingungen
  • sollten daher für Methoden einer als Basisklasse
    entworfenen Klasse ausdrücklich spezifiziert sein
  • ansonsten ist beim Überschreiben von Methoden
    nicht erkennbar, ob das LSP evtl. verletzt wurde
    (möglicherweise unbeabsichtigt)

14
Überladen und Überschreiben(Overloading and
Overriding)
  • Von Überladen spricht man wenn
  • mehrere Methoden (oder globale Funktionen) mit
    identischem Namen aber unterschiedlicher Anzahl
    bzw. unterschiedlichem Typ von Argumenten
    existieren
  • die beim Aufruf angegebenen Argumente bestimmen,
    welche Methode aufgerufen wird
  • Von Überschreiben spricht man wenn
  • eine abgeleitete Klasse eine Methode ihrer
    Basisklasse durch eine gleichnamige Methode
    ersetzt
  • hierdurch werden zugleich alle überladenen
    Methoden der Basisklasse verdeckt
  • die abgeleitete Klasse sollte daher ggf. alle
    überladenen Methoden überschreiben

15
inline vs. normale Methoden
  • Methoden (Member-Funktionen von Klassen)
  • entsprechen üblicherweise Unterprogrammen
  • mit einem zusätzlich (versteckt) übergebenen
    Argument (this-Zeiger)
  • Bei Verwendung von inline
  • wird der Methoden-Inhalt (Body) an der
    Aufrufstelle direkt eingesetzt
  • im Unterschied zu Präprozessor Makros erfolgt
    dies semantisch korrekt
  • Normalerweise ergibt sich mit inline
  • eine etwas bessere Ausführungsgeschwindigkeit
  • aber mehr Bedarf an Speicherplatz (im Code)
  • der konkret von der Zahl der Methoden-Aufrufstelle
    n abhängt
  • Im Fall sehr kleiner Methoden kann inline
  • deutlich schnelleren Code erzeugen (da bessere
    Lokalität)
  • der im Gesamtumfang sogar kleiner ist

16
Compilezeit-Typ und Laufzeit-Typ
  • Der Compilezeit-Typ einer Variablen
  • ist der aus der Deklaration/Definition
    ersichtliche Typ
  • bestimmt bei Objekten, welche Methoden aufgerufen
    werden können
  • Der Laufzeit-Typ einer Variablen
  • kann bei einem Zeiger oder einer Referenz auch
    eine vom Compilezeit-Typ abgeleitete Klasse sein
    (LSP!)
  • stimmt ansonsten mit dem Compilezeit-Typ überein
  • legt im Falle virtueller Methoden fest, welche
    Methode tatsächlich aufgerufen wird
  • kann bei Bedarf mittels RTTI (Runtime-Type-Informa
    tion) ermittelt werden

17
Virtuelle Methoden
  • Ein großer Teil der Flexibilität
    Objektorientierter Programmierung resultiert aus
    der Verwendung virtueller Methoden
  • Sie verschieben externe Fallunterscheidungsketten
    in die Klassenhierarchie selbst und
  • führen damit zu besserer Wartbarkeit und
    Erweiterbarkeit
  • Virtuelle Methoden haben grundsätzlich einen
    geringfügigen Overhead
  • der relativ betrachtet um so mehr ins Gewicht
    fällt, je weniger Code die Methode enthält
  • bei sehr kleinen Methoden ist daher der Vorteil
    der flexiblen Erweiterbarkeit gegenüber dem
    Geschwindigkeits-Nachteil abzuwägen

18
Virtuelle und Methoden und inline
  • Der Aufrufmechanismus für virtuelle Methoden
  • erlaubt die Auswahl gemäß dem Laufzeit-Typ
  • setzt aber den Weg über eine Einsprungtabelle
    voraus
  • insofern muss immer ein Unterprogramm-Sprung
    erfolgen
  • Da sich Compilezeit- und Laufzeit-Typ aber nur
    bei Bezugnahme über Zeiger und Referenzen
    unterscheiden können
  • ist der Weg über die Sprungtabelle nicht
    erforderlich, wenn das Objekt direkt angesprochen
    wird
  • entfaltet inline in diesem Fall auch bei
    virtuellen Methoden seine Wirkung

19
Mehrfachvererbung undVirtuelle Basisklassen
  • Mehrfachvererbung
  • bezeichnet den Fall, dass eine Klasse mehr als
    eine Basisklasse hat
  • ist so lange unproblematisch, wie die
    Vererbungslinien nicht wieder in einer
    gemeinsamen Basisklasse zusammentreffen
  • Ist letzteres doch der Fall, wird die gemeinsame
    Basisklasse per Default mehrfach enthalten sein
    (disjoint)
  • weshalb das LSP nicht mehr für diese gemeinsame
    Basisklasse greift
  • Virtuelle Basisklassen
  • sind die Lösung für den Fall, dass eine
    gemeinsame Basisklasse bei Mehrfachvererbung nur
    einmal enthalten sein soll (overlapping)
  • bedingen Overhead durch einen zusätzliche Zeiger
    (pro Objekt) in den direkt abgeleiteten Klassen
    und eine Indirektionsstufe (bei Zugriff auf
    Attribute der virtuellen Basisklasse)
  • sind in besondere Weise in Initialisierungs-Listen
    zu berücksichtigen (Initialisierung muss von der
    most derived class ausgehen)

20
Runtime-Type-Information (RTTI)
  • Mittels dynamic_cast kann ermittelt werden,
  • ob der Laufzeit-Typ ggf. wie der in der
    Cast-Operation vorgegebene Typ verwendbar wäre
  • also ob er exakt diesem Typ entspricht
  • oder dem einer davon abgeleiteten Klasse
  • Die Anwendung ist nur im Zusammenhang mit Klassen
    möglich, die wenigstens eine virtuelle Methode
    haben
  • Mittels typeid kann ermittelt werden,
  • ob der Laufzeit-Typ exakt einem bestimmten Typ
    entspricht
  • können einige weitere Informationen zum
    betreffenden Typ gewonnen werden (z.B. eine
    Text-Darstellung)
  • Die Anwendung ist auch auf die in C enthaltenen
    Grundtypen und Klassen ohne virtuelle Methoden
    möglich
  • bezieht sich dann allerdings auf den
    Compilezeit-Typ!

21
Entwurfsmuster Template Method
  • Im Sinne des Open-Close-Principles
  • wird hier ein fest vorgegebener Ablauf ( close)
  • an vorher festgelegten Stellen mit variabel zu
    füllenden Erweiterungspunkten ausgestattet (
    open)
  • Die klassische Implementierung der letzeren
  • erfolgt mit Hilfe virtueller Methode
  • die von abgeleiteten Klassen nach Bedarf
    implementiert werden
  • Alternativ kann dieses Muster auch
  • auf C-Templates zurückgreifen und
  • Erweiterungspunkte in einer bei der späteren
    Template-Instanziierung anzugebenden Basisklasse
    implementieren

22
Ressource-Management
  • Konstruktoren
  • sind verantwortlich für die Bereitstellung von
    Ressourcen, die ein Objekt privat (für sich
    allein) benötigt
  • werden bei der Definition des Objekts automatisch
    aufgerufen (können also nicht vergessen werden)
  • Destruktoren
  • sind verantwortlich für die Freigabe von
    Ressourcen, die ein Objekt privat (für sich
    allein) benötigt
  • werden am Ende der Lebensdauer des Objekts
    automatisch aufgerufen (können also nicht
    vergessen werden)
  • Bereitstellung und Freigabe privater Ressourcen
    außerhalb von Konstruktoren / Destruktoren ist
    fehlerträchtiger und nur in seltenen Fällen
    sinnvoll.

23
Ressource-Leaks (1)
  • Hierunter versteht man u.a. den schleichenden
    Verlust an verfügbarem Hauptspeicher,
  • wenn ein Zeigers zwar mit new initialisiert wird,
  • das referenzierte Objekt aber nicht vor Ende der
    Lebensdauer des Zeigers mit delete wieder
    freigegeben wird
  • Um Ressource-Leaks im Fall von Exceptions
    vorzubeugen
  • ist sicherzustellen, dass die Freigabe einer
    bereits erfolgreich belegten Ressource in jedem
    Fall geschieht,
  • z.B. indem alle Operationen, die möglicherweise
    (direkt oder indirekt) ein throw auslösen), in
    einen try-Block eingeschlossen werden,
  • sodass ein nachfolgender catch-Block die Freigabe
    vornehmen kann
  • Ist eine Gruppe von Ressourcen zu belegen
  • kann die Anforderung nur eine nach der anderen
    geschehen,
  • womit sich (ohne RAII) verschachtelte try-Blöcke
    ergeben

24
Ressource-Leaks (2)
  • Ein sehr bekanntes Problem, das zu
    Ressource-Leaks führen kann, wenn keine
    Vorkehrung dagegen getroffen werden,
  • sind Klassen, die im Konstruktor Speicherplatz
    mit new anfordern,
  • in einem lokalen (Member-) Attribut halten
  • bis dieser im Destruktor wieder freigegeben wird.
  • Solche Klassen müssen zugleich
  • den per Default erzeugten Kopier-Konstruktor und
    Zuweisungs-Operator vermeiden
  • indem entweder entsprechende eigene Methoden
    definiert
  • oder zumindest deklariert und nicht implementiert
    werden
  • C0x erlaubt darüberhinaus das Sperren der per
    Default erzeugten Kopier- und Zuweisungs-Operation
    en mittels einer speziellen, neuen Syntax

25
Ressource-Leaks (3)
  • Scheitert die Anforderung einer Ressource in
    einem Konstruktor
  • muss das Problem lokal gelöst werden,
  • da der Destruktor für ein Objekt erst dann
    freigeschaltet wird, wenn der Konstruktor
    vollständig und fehlerfrei sein Ende erreicht hat
  • Die Behandlung von Problemen bei der
    Anforderungen im Konstruktor
  • führt oft zu geschachtelten try-Blöcken,
  • die sich u.U. auch über die MI-Liste erstrecken
    müssen
  • Eine ebenso wirksame aber deutlich elegantere
    Lösung bieten Ressource-Wrapper (RAII)

26
Vorsichtsmaßnahmen bei der Verwendung von
Auto-Pointern
  • Bei der Initialisierung ist sicherzustellen,
  • dass ein Zeiger auf frischen ( mit new
    angeforderten) Heap-Speicherplatz verwendet wird
  • der Zeiger darf nicht von new geliefert worden
    sein
  • der Zeiger darf nicht mit dem Adress-Operator
    bestimmt worden sein
  • der Zeiger darf nicht von einem anderen
    Auto-Pointer mit get ermittelt worden sein
  • Zur Übergabe eines Auto-Pointers als Argument an
    eine Funktion ist meist eine Referenz sinnvoll
  • Bei der Wert-Übergabe wird
  • die Eigentümerschaft auf den Parameter übertragen
  • das referenzierte Objekt mit Ende der Funktion
    gelöscht und
  • der als aktuelles Argument verwendete
    Auto-Pointer zum Nullzeiger
  • Die Rückgabe eines Auto-Pointer in einer
    return-Anweisung ist OK und sinnvoll (z.B. aus
    Factory-Funktionen/-Methoden)

27
Lebensdauer von Objekten
  • Globale Objekte und Klassen-Attribute (static
    Member) werden
  • vor dem Start der main-Funktion initialisiert und
  • nach dem Ende von main-Funktion aufgeräumt
  • Block-lokale static Objekte werden
  • direkt vor der ersten Verwendung initialisiert
    und
  • nach dem Ende der main-Funktion aufgeräumt
  • Block-lokale automatische Objekte werden
  • wenn der Kontrollfluss ihre Definitionsstelle
    erreicht initialisiert und
  • wenn der Kontrollfluss den enthaltenden Block
    verlässt aufgeräumt
  • Auf dem Heap angelegte Objekte
  • werden im Rahmen der new-Anweisung initialisiert
    und
  • im Rahmen der delete-Anweisung aufgeräumt
  • Sie werden jedoch nicht aufgeräumt, wenn
    lediglich die Lebensdauer des auf sie verweisende
    Zeigers endet.

28
Klasse stdauto_ptr
  • Auto-Pointer bieten einen leichtgewichtigen
    Ersatz für Zeiger
  • Sie gehen davon aus, dass sie Eigentümer des
    über sie erreichbaren Speicherplatzes sind
  • ein Konstruktor sorgt für dessen Initialisierung
  • ein Destruktor räumt am Ende der Lebensdauer des
    Auto-Pointer das dadurch referenzierte Objekt weg
  • Damit sichergestellt ist, dass immer nur genau
    ein Auto-Pointer ein bestimmtes Objekt
    bezeichnet, wird
  • im Kopierkonstruktor der zur Initialisierung
    verwendete Auto-Pointer zum Null-Pointer gemacht
  • im Zuweisungsoperator der auf der rechten Seite
    stehende Auto-Pointer zum Null-Pointer gemacht

29
Gemischte Verwendung von auto_ptrltTgt und T
  • Die get-Methode eines Auto-Pointer
  • gibt die Adresse des referenzierten Objekts
    zurück
  • aber der Auto-Pointer ist weiterhin der
    Eigentümer, wird also zum Ende seiner Lebensdauer
    das referenzierte Objekt löschen
  • Sinnvoll, um einem Dritten Zugriff auf das
    referenzierte Objekt zu geben
  • Dieser darf den erhaltenen Zeiger nur nicht in
    einer langlebigen Variablen speichern
  • Die release-Methode eines Auto-Pointer
  • gibt die Adresse des referenzierten Objekts
    zurück
  • macht den Auto-Pointer in diesem Fall aber zum
    Nullzeiger
  • Sinnvoll, um einem Dritten die Eigentümerschaft
    des Objekts zu übertragen
  • Dieser darf nur nicht vergessen, den über den
    erhaltenen Zeiger erreichbaren Speicherplatz
    irgendwann mittels delete freizugeben

30
Ressource Acquisition is Initialization (RAII)
  • Ein u.a. von Bjarne Stroustrup favorisiertes
    Idiom, gemäß dem
  • für Ressourcen mit expliziten Anforderungs- und
    -Freigabe-Operation ein Objekt angelegt werden
    sollte (Ressource-Wrapper)
  • das in seinem Konstruktor die Anforderungs-Operati
    on und
  • in seinem Destruktor die Freigabe-Operation
    durchführt.
  • Vorteile eines solchen Ressource-Wrappers sind,
    dass die Anforderung/Freigabe einfach und
    risikolos
  • an einen Code-Block gebunden werden kann, indem
    dort ein lokales Wrapper-Objekt angelegt wird
  • an die Lebensdauer eines Objekts gebunden werden
    kann, indem dort ein Wrapper-Objekt als Attribut
    angelegt wird

31
Verwendung von Exceptions
  • Die Verwendung der throw-Anweisung im Fehlerfall
    entspricht einem go-to auf einen passenden
    catch-Block
  • Es kommen nur catch-Blöcke in Betracht, deren
    vorangehender try-Block noch aktiv ist
  • der Kontrollfluss verzweigt somit grundsätzlich
    zurück in Richtung auf main
  • Passend bedeutet, dass
  • der Typ des formalen Parameters im catch-Block
    mit dem Typ des Ausdrucks nach throw
    übereinstimmt
  • oder letzterer in ersteren umwandelbar ist, und
    zwar nach den selben Regeln wie bei einem
    Funktions-Aufruf
  • Folgen ein und demselben try-Block sowohl
    catch-Blöcke für Basisklassen wie auch davon
    abgeleiteten Klassen
  • sind letztere weiter vorne anzuordnen
  • sonst werden sie niemals ausgeführt

32
Typ des Exception-Objekts
  • C macht keine Einschränkungen hinsichtlich des
    Typs, der als Exception geworfen wird
  • Grundtypen (z.B. int oder enum als Fehler-Code)
    funktionieren ebenso
  • wie Zeiger (z.B. const char oder stdstring
    als Fehlermeldung)
  • und Klassen (Standardklassen oder selbst
    definierte)
  • Dennoch ist es ist es empfehlenswert, eigene
    Exception-Klassen von der Standard-Klassenhierarch
    ie für Exceptions abzuleiten, z.B.
  • stdlogic_error wenn das Problem durch einen
    Programmierfehler verursacht wurde und zur
    Beseitigung der Programm-Quelltext geändert und
    neu kompiliert werden muss
  • stdruntime_error wenn das Problem eine äußere
    Ursache hat, die zu seiner Beseitigung zu beheben
    ist
  • stdexception Mindestanforderung, damit ein
    zentraler catch-Block den what-Text nicht
    behandelter Fehler ausgeben kann

33
Lebensdauer des Exception-Objekts
  • Der bei der throw-Anweisung angegebene Ausdruck
  • wird (zumindest formal) kopiert,
  • in einen Speicherbereich der auch bei der
    Ausführung des catch-Blocks noch zur Verfügung
    steht
  • Um ein nochmaliges Kopieren zu vermeiden
  • sollte das Argument des catch-Blocks eine
    Referenz sein, und
  • falls der catch-Block die Exception weiterreichen
    muss, lediglich die Anweisung throw (ohne
    nachfolgenden Ausdruck) benutzt werden
  • Die Verwendung von Zeigern als Exception-Objekte
    ist
  • nicht nur überflüssig sonder auch
  • unnötig fehlerträchtig

34
Performance von Exceptions
  • Die Implementierung von Exceptions ist im
    ISO/ANSI-Standard von C nicht exakt vorgegeben
  • typischerweise ist der Code für den Normalfall
    ( kein throw) ähnlich schnell wie ein return
  • beim tatsächlichen Auslösen einer Exception
    aber sehr viel langsamer

35
Overhead von Exceptions
Write a Comment
User Comments (0)
About PowerShow.com