In Wann soll C über C ++ und C ++ über C verwendet werden? es gibt eine aussage bezüglich Code Größe / C ++ Ausnahmen:
Jerry antwortet (unter anderem):
(...) Es ist in der Regel schwieriger, mit C ++ wirklich winzige ausführbare Dateien zu erstellen. Bei wirklich kleinen Systemen schreiben Sie sowieso selten viel Code, und die (...)
worauf ich fragte warum das so sei, worauf Jerry antwortete:
Die Hauptsache ist, dass C ++ eine Ausnahmebehandlung beinhaltet, die (zumindest normalerweise) der ausführbaren Größe ein Minimum hinzufügt. Bei den meisten Compilern können Sie die Ausnahmebehandlung deaktivieren, aber wenn Sie dies tun, ist das Ergebnis nicht mehr ganz C ++. (...)
An der technischen Realität bezweifle ich nicht wirklich.
Daher bin ich (aus reiner Neugier) daran interessiert, Beispiele aus der Praxis zu hören, bei denen ein Projekt C ++ als Sprache auswählte und dann Ausnahmen deaktivierte. (Nicht nur "keine" Ausnahmen im Benutzercode verwenden, sondern sie im Compiler deaktivieren, damit Sie keine Ausnahmen auslösen oder abfangen können.) Warum hat sich ein Projekt dafür entschieden (immer noch C ++ und nicht C, aber nein) Ausnahmen) - Was sind / waren die (technischen) Gründe?
Nachtrag: Für diejenigen, die ihre Antworten näher erläutern möchten, wäre es hilfreich, detailliert darzulegen, wie die Auswirkungen von Nicht-Ausnahmen gehandhabt werden:
- STL-Sammlungen (
vector
, ...) funktionieren nicht ordnungsgemäß (Zuordnungsfehler können nicht gemeldet werden) new
kann nicht werfen- Konstruktoren können nicht fehlschlagen
quelle
Antworten:
Fast jedes Konsolenspiel gibt es in C ++ mit Ausnahme deaktiviert, auch heute noch. In fac ist dies die Standardkonfiguration für C ++ - Compiler, die auf diese Konsolen abzielen. Manchmal funktionieren einige C ++ - Funktionen auf diesen Compilern nicht richtig, wie beispielsweise die Mehrfachvererbung (ich denke beispielsweise an einen sehr bekannten Konsolen-Standard-Compiler).
Ein weiteres Beispiel ist das in C ++ ausnahmslos aktivierte Arduino-Hardware-SDK usnig gcc und andere Dinge, wie z . B. keine STL .
Es gibt einige technische Gründe, gute oder schlechte, was auch immer, es ist nicht mein Rat, aber Gründe, die ich gehört habe:
Ich denke, Ausnahmen können sogar in Spielen nützlich sein, aber das stimmt, dass es in Konsolenspielen nicht wirklich nützlich ist.
Aktualisieren:
Ich füge hier ein weiteres überraschendes Beispiel hinzu: LLVM / CLang verwenden weder Ausnahme noch RTTI aus den folgenden Gründen :
CLang ist bekannt für seine Geschwindigkeit beim Kompilieren und für explizite Fehler, aber auch für seinen seltenen Compiler, der wirklich einfach zu verfolgenden Code enthält.
quelle
Jerry sagte: ... das Ergebnis ist nicht ganz C ++ mehr , während meine Metapher ist , dass es ist klar C ++, nur ein etwas anderer Dialekt , weil Programme andere Formen verwenden, Konventionen und geschrieben Stile.
Hier sind meine Hauptgründe für die Deaktivierung:
Binäre Kompatibilität
Das Überschreiten von Sprach- und Übersetzungsgrenzen ist nicht allgemein definiert oder undefiniert. Wenn Sie sicherstellen möchten, dass Ihr Programm im Bereich des definierten Verhaltens ausgeführt wird, müssen Sie Ausnahmen an Modul-Exit-Punkten unter Quarantäne stellen.
Ausführbare Größe
Hier sind die Binärgrößen eines ausnahmefreien Programms, das ich ohne und mit aktivierten Ausnahmen geschrieben habe:
Ohne Ausnahmen:
Mit Ausnahmen:
Erinnerung: Dies ist eine Sammlung von Bibliotheken und Programmen, die keine Throws / Catches enthalten. Der Compiler - Flag tut Ausnahmen in der Standardbibliothek C ++ ermöglichen. Daher betragen die Kosten in der realen Welt in diesem Beispiel mehr als 19%.
Compiler: apple gcc4.2 + llvm. Größen in MB.
Geschwindigkeit
Trotz des Begriffs "Null-Kosten-Ausnahmen" erhöhen sie den Overhead, auch wenn nie etwas anfällt. Im obigen Fall handelt es sich um ein leistungskritisches Programm (Signalverarbeitung, Generierung, Präsentation, Konvertierung, mit großen Datenmengen / Signalen usw.). Ausnahmen sind in diesem Design nicht erforderlich, während die Leistung sehr wichtig ist.
Programmkorrektheit
Scheint ein seltsamer Grund zu sein ... Wenn das Werfen keine Option ist, müssen Sie relativ strenge, korrekte und gut getestete Programme schreiben, um sicherzustellen, dass Ihr Programm korrekt ausgeführt wird und die Clients die Schnittstellen korrekt verwenden (wenn Sie mir ein schlechtes Argument geben oder dies tun) Überprüfen Sie keinen Fehlercode, dann verdienen Sie UB). Das Ergebnis? Die Implementierungsqualität wird erheblich verbessert und Probleme werden schnell behoben.
Einfachheit
Implementierungen zur Ausnahmebehandlung werden häufig nicht auf dem neuesten Stand gehalten. Sie erhöhen auch die Komplexität, da eine Implementierung viele, viele Exit-Sequenzen haben kann. Es ist einfacher, hochkomplexe Programme zu lesen und zu warten, wenn sie einen kleinen Satz gut definierter, typisierter Exit-Strategien verwenden, die dem Client zuwiderlaufen und vom Client gehandhabt werden. In anderen Fällen können die Implementierungen im Laufe der Zeit mehr Throws implementieren, oder ihre Abhängigkeiten können sie einführen. Kunden können sich nicht einfach oder angemessen gegen all diese Ausgänge verteidigen. Ich schreibe und aktualisiere viele Bibliotheken, es gibt häufige Entwicklungen und Verbesserungen. Der Versuch, dies alles mit den Exit-Sequenzen von Ausnahmen (in einer großen Codebasis) synchron zu halten, wäre kein guter Zeitgewinn und würde wahrscheinlich viel Lärm und Kruft verursachen. Durch erhöhte Programmkorrektheit und mehr Tests
Verlauf / bestehender Code
In einigen Fällen wurden sie aus historischen Gründen nie eingeführt. Eine vorhandene Codebasis hat sie nicht verwendet. Das Ändern der Programme kann Jahre dauern und die Wartung aufgrund von Überschneidungen bei Konventionen und Implementierungen sehr hässlich machen.
Nachteile
Natürlich gibt es Nachteile, die größten sind: Inkompatibilität (einschließlich Binärdateien) mit anderen Bibliotheken und die Tatsache, dass Sie eine gute Anzahl von Programmen implementieren müssen, um dieses Modell zu erfüllen.
quelle
malloc
Retouren0
), gibt der Allokator eine ein,while (1)
die einen Kontextwechsel aufweist, gefolgt von einem weiteren Versuch der Zuordnung. In dieser Codebasis war es früher so, dass new über den Allokator 0 zurückgeben konnte, aber die neuere Implementierung hat einwandfrei funktioniert. (Fortsetzung)Google erkennt Ausnahmen in seinem C ++ Style Guide nicht an , hauptsächlich aus historischen Gründen:
(Schwerpunkt der Redaktion)
quelle
Qt verwendet fast nie Ausnahmen. Fehler in Qt werden durch Fehlercodes und -signale angezeigt. Der offiziell angegebene Grund ist:
Heutzutage wird Qt häufig kritisiert, dass seine Ausnahmesicherheit nicht vollständig ist.
quelle
Symbian C ++ (wird auf einigen Nokia-Mobiltelefonen verwendet) verwendet keine Ausnahmen, zumindest nicht direkt, da C ++ - Compiler diese bei der Entwicklung von Symbian nicht zuverlässig implementiert haben.
quelle
Ich verwende keine Ausnahmen. Dafür gibt es eine Reihe von Gründen, aber die beiden Hauptgründe sind, dass ich sie nie benötigt habe, um robusten Code zu erstellen, und dass sie die Leistung zur Laufzeit verringern.
Ich habe an Produktionscode gearbeitet, der Ausnahmen verwendet und deaktiviert - der Code, der Ausnahmen zulässt, war einheitlich schlechter. An einigen Stellen wurden Ausnahmen eher für eine echte Ablaufsteuerung als für die Fehlerbehandlung verwendet, die sehr schwer, leistungsschwach und schwer zu debuggen ist. Im Allgemeinen war das Debuggen von Problemen mit dem Code, der mit Ausnahmen gefüllt wurde, schwieriger als mit dem Code, der keine Ausnahmen enthält. Dies lag zum Teil am Stack und den eigentlichen Schwierigkeiten des Ausnahmemechanismus Ergebnis der verfügbaren Ausnahmebehandlung.
An den Ausnahmen selbst ist nichts ernsthaft auszusetzen / wenn Sie sich nicht um die Leistung kümmern / und keine Zeit haben, etwas richtig zu machen - sie sind eine Sprachfunktion für die Fehlerbehandlung und ein guter Ersatz für einen ordnungsgemäßen Fehlerbehandlungsmechanismus. Es gibt jedoch fast immer / bessere / Möglichkeiten, um mit Fehlern umzugehen - wie mit Ihrer eigenen Logik (es ist schwierig, dies zu erläutern - es ist fast normaler Menschenverstand). Wenn es nicht Ihr Fehler ist, sondern aus einer Bibliothek (z. B. der Standardbibliothek) stammt, müssen Sie die Auswahl der Ausnahmen respektieren oder einen Absturz erleiden, aber ich würde diese Auswahl immer in Frage stellen. Ich habe noch nie eine Situation gesehen, in der Ausnahmen tatsächlich die beste Lösung waren.
Behauptungen sind leichter zu debuggen, Fehlercodes sind weniger schwer zu handhaben. Wenn sie richtig verwendet werden, können Sie Code leichter lesen, debuggen und warten, was schneller ist. Es gewinnt rundum ...
quelle
Im C ++ - Codierungsstandard von Joint Strike Fighter von Bjarne et. Ausnahmen sind aufgrund der hohen Echtzeitanforderungen von Kampfflugzeugen verboten.
Zitiert aus Bjarnes C ++ FAQ .
Denken Sie daran, dass C ++ wahrscheinlich die größte Auswahl an Software aller Sprachen ausführt ...
quelle
Das ist im C ++ - Bibliotheksdesign ziemlich wichtig. Oft ist es mit einer C-Schnittstelle ziemlich unangenehm, eine Ausnahme aus der Bibliothek eines Drittanbieters auf den Client zu werfen. Das bedeutet, dass Sie, wenn Ihre Bibliothek wirft, eine Reihe von Clients ausschneiden, die sie verwendet hätten, da sie eine Garantie für das Nicht-Werfen hatten (aus welchem Grund auch immer der Client Ausnahmen einschränkt).
Persönlich habe ich Ausnahmen gesehen, die missbraucht wurden, wenn das Team angewiesen wurde, "eine Ausnahme einzulegen", wenn etwas nicht so Schreckliches passiert. Natürlich sehen Sie den Fehler hier - die Ausnahme wurde in den Code geworfen, bevor jemand herausgefunden hat, was damit zu tun ist. Dieses Projekt hatte ein paar Abstürze, da diese Tiefschläge gelegentlich auftauchten.
quelle
Vielleicht lohnt es sich in diesem Zusammenhang, Embedded C ++ zu erwähnen . Embedded C ++ ist eine Variante von C ++, die (offensichtlich genug) für eingebettete Systeme entwickelt wurde. Es handelt sich im Grunde genommen um eine richtige Teilmenge von C ++, wobei (unter anderem) Vorlagen, Namespaces und die Behandlung von Ausnahmen entfernt wurden.
Ich sollte hinzufügen, dass EC ++ zwar ein wenig Aufsehen erregt hat, als es neu war, dass es aber anscheinend größtenteils ziemlich ruhig geworden ist. Ich bin mir nicht sicher, ob die Leute das Interesse verloren haben oder ob ihr erster Versuch einfach so perfekt war, dass seit etwa einem Jahrzehnt niemand mehr einen Grund gesehen hat, sich damit herumzuschlagen.
<closed captioning for the humor impaired>Yeah, right!</closed captioning>
quelle
Ein gutes Beispiel ist die Kernelmodus-Programmierung.
Sie können C ++ dort für saubereren Code verwenden, aber ohne Ausnahmen. Es gibt keine Laufzeitbibliothek für sie und die Ausnahmebehandlung verbraucht zu viel Stapelspeicher, der im Kernel sehr begrenzt ist (ich habe mit C ++ - Ausnahmen im Windows NT-Kernel experimentiert und das Auslösen und Rückgängigmachen von Ausnahmen verbraucht die Hälfte des verfügbaren Stapels - sehr einfach, um einen Stapelüberlauf zu erhalten und das ganze System zum Absturz bringen).
In der Regel definieren Sie Ihre eigenen
new
unddelete
Operatoren. Auch ich fand ziemlich handlicheplacement new
a- und c ++ 11-Werte-Referenzen. Es können keine STL- oder anderen C ++ - Benutzermodusbibliotheken verwendet werden, die auf Ausnahmen basieren.quelle
Wenn Sie versuchen, den ausführbaren Speicher niedrig zu halten. Wird normalerweise auf eingebetteten (oder mobilen) Systemen ausgeführt. Für Desktops-Apps, die auf Servern nie benötigt werden, kann es in Betracht gezogen werden, ob Sie für den Webserver oder für SQL so viel RAM wie möglich benötigen.
quelle