it-swarm.dev

Gibt es ausnahmslos reale Fälle für C ++?

In Wann soll C über C++ und C++ über C verwendet werden? gibt es eine Anweisung wrt. zu Codegröß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 das Extra (...)

worauf ich fragte, warum das so sei, worauf Jerry antwortete:

die Hauptsache ist, dass C++ eine Ausnahmebehandlung enthält, 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++. (...)

was ich auf der Ebene der technischen Realität nicht wirklich bezweifle.


Daher bin ich (nur aus Neugier) daran interessiert, von Beispielen aus der Praxis zu hören, in denen ein Projekt C++ als Sprache gewählt und dann Ausnahmen deaktiviert hat. (Verwenden Sie Ausnahmen im Benutzercode nicht nur "nicht", sondern deaktivieren Sie sie im Compiler, damit Sie keine Ausnahmen auslösen oder abfangen können.) Warum hat sich ein Projekt dafür entschieden (weiterhin 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 schön, detailliert zu beschreiben, wie mit den Auswirkungen von Ausnahmen umgegangen wird:

  • STL-Sammlungen (vector, ...) funktionieren nicht ordnungsgemäß (Zuordnungsfehler können nicht gemeldet werden)
  • new kann nicht werfen
  • Konstruktoren können nicht versagen
40
Martin Ba

Fast jedes Konsolenspiel gibt es in C++, mit Ausnahme der Deaktivierung, auch heute noch. In Fac ist dies die Standardeinstellung für C++ - Compiler, die auf diese Konsolen abzielen. Manchmal kann nicht garantiert werden, dass einige C++ - Funktionen auf diesen Compilern ordnungsgemäß funktionieren, wie z. B. Mehrfachvererbung (ich denke beispielsweise an einen sehr bekannten Standard-Compiler für Konsolen).


Ein weiteres Beispiel ist Arduino Hardware SDK usnig gcc ohne Ausnahme in C++ aktiviert, und andere Dinge wie keine STL bereitgestellt .


Es gibt einige technische Gründe, gut oder schlecht, was auch immer, es ist nicht mein Rat, sondern Gründe, die ich gehört habe:

  1. Die meisten Konsolen sind wirklich eingebettete Systeme mit begrenztem Speicher und begrenzter Verarbeitungszeit. Vielleicht wird es in zukünftigen Konsolen nicht so wahr sein, aber aktuelle sind im Vergleich zu einem PC immer noch recht restriktiv. Einige tragbare Konsolen sind im Allgemeinen schwieriger zu programmieren als jedes Smartphone, beispielsweise das NDS. Die Ausnahmefunktion erhöht den Speicher und die Geschwindigkeitskosten, auch wenn Sie sie nicht verwenden. Sie können sich selbst überprüfen, es ist sogar auf dem PC wahr.
  2. Videospiele auf der Konsole können nicht abstürzen. Sie müssen so getestet werden, dass ein Absturz, eine Sackgasse oder ein Showstoper vermieden wird. Aus diesem Grund bitten Konsolenhersteller, die Spiele vor der Veröffentlichung gründlich zu überprüfen. Das bedeutet auch, dass das Ausnahmemanagement zusätzliche Kosten verursacht, die bei Konsolenspielen nicht wirklich nützlich sind. Dies ist beispielsweise auf Smartphones besser, da es möglicherweise Möglichkeiten zur Wiederherstellung oder zum Hinzufügen von Code gibt, um Ihnen das Problem per E-Mail zu senden. Geschlossene Plattformen wie die meisten Konsolen erlauben dies nicht. Ein Ausnahmesystem ist also doch nicht wirklich notwendig. Sie müssen "nur dafür sorgen, dass es richtig funktioniert". ;)
  3. Wenn Sie bei der Ausnahmeverwaltung keine Fehler und Abstürze zulassen, müssen Sie eine Fehlerverwaltungsstrategie implementieren. Ein solches System kann komplex genug sein, damit jemand viel Zeit arbeitet, um es nützlich zu machen. Spieleentwickler haben keinen Luxus, an Funktionen zu arbeiten, von denen angenommen wird, dass sie bei Abstürzen nützlich sind ...
  4. Der Compiler erlaubt es (noch) nicht. Ja, es passiert.

Ich denke, Ausnahmen können sogar in Spielen nützlich sein, aber das stimmt, dass es bei Konsolenspielen nicht wirklich nützlich ist.


Aktualisieren:

Ich füge hier ein weiteres überraschendes Beispiel hinzu: LLVM/CLang verwendet aus den folgenden Gründen weder Ausnahme noch RTTI :

Um den Code und die Größe der ausführbaren Dateien zu reduzieren, verwendet LLVM keine RTTI (z. B. dynamic_cast <>) oder Ausnahmen. Diese beiden Sprachfunktionen verstoßen gegen das allgemeine C++ - Prinzip "Sie zahlen nur für das, was Sie verwenden" und führen zu einem Aufblähen der ausführbaren Datei, selbst wenn in der Codebasis niemals Ausnahmen verwendet werden oder wenn RTTI niemals für eine Klasse verwendet wird. Aus diesem Grund deaktivieren wir sie global im Code.

Allerdings verwendet LLVM in großem Umfang eine handgerollte Form von RTTI, die Vorlagen wie isa <>, cast <> und dyn_cast <> verwendet. Diese Form von RTTI ist opt-in und kann zu jeder Klasse hinzugefügt werden. Es ist auch wesentlich effizienter als dynamic_cast <>.

CLang ist bekannt für seine schnelle Kompilierung und explizite Fehler, aber auch für seinen seltenen Compiler, der wirklich einfach zu verfolgenden Code enthält.

35
Klaim

Jerry sagte: ... das Ergebnis ist nicht mehr ganz C++ , während meine Metapher ist, dass es ist eindeutig C++, nur ein etwas anderer Dialekt , da Programme andere Formen, Konventionen und geschriebene Stile verwenden.

Hier sind meine Hauptgründe für die Deaktivierung:

Binärkompatibilitä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 den Modul-Exit-Punkten unter Quarantäne stellen.

Ausführbare Größe

Hier sind die Binärgrößen eines ausnahmefreien Programms, das ich geschrieben und ohne und mit aktivierten Ausnahmen erstellt habe:

Ohne Ausnahmen:

  • ausführbare Datei + Abhängigkeiten: 330
  • endgültige gestrippte ausführbare Datei (Release Build): 37

Mit Ausnahmen:

  • ausführbare Datei + Abhängigkeiten: 380
  • endgültige gestrippte ausführbare Datei (Release Build): 44

Erinnerung: Dies ist eine Sammlung von Bibliotheken und Programmen, die keine Würfe/Fänge enthalten. Das Compiler-Flag aktiviert Ausnahmen in der C++ - Standardbibliothek. 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 Aufwand, selbst wenn nie etwas geworfen wird. Im obigen Fall handelt es sich um ein leistungskritisches Programm (Signalverarbeitung, Generierung, Präsentation, Konvertierung, mit großen Datenmengen/Signalen usw.). Ausnahmen sind bei 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 dass 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 verbessert sich erheblich und Probleme werden schnell behoben.

Einfachheit

Implementierungen für die 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 gerecht werden und von ihm verwaltet werden. In anderen Fällen können die Implementierungen im Laufe der Zeit mehr Würfe 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, alles mit Ausnahme-Exit-Sequenzen (in einer großen Codebasis) synchron zu halten, wäre kein guter Zeitaufwand und würde wahrscheinlich viel Rauschen und Kruft verursachen. Aufgrund der erhöhten Programmkorrektheit und mehr Tests können viele (sicherlich nicht alle) potenzielle Probleme/Exits ausgeschlossen werden.

Verlauf/vorhandener 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 viele 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 (inkl. Binär) mit anderen Bibliotheken und die Tatsache, dass Sie eine gute Anzahl von Programmen implementieren müssen, um zu diesem Modell zu passen.

9
justin

Google genehmigt keine Ausnahmen in ihrem C++ Style Guide , hauptsächlich aus historischen Gründen:

Auf den ersten Blick überwiegen die Vorteile der Verwendung von Ausnahmen die Kosten, insbesondere bei neuen Projekten. Für vorhandenen Code hat die Einführung von Ausnahmen jedoch Auswirkungen auf alle abhängigen Codes. Wenn Ausnahmen über ein neues Projekt hinaus weitergegeben werden können, wird es auch problematisch, das neue Projekt in vorhandenen ausnahmefreien Code zu integrieren. Da der meiste bei Google vorhandene C++ - Code nicht auf Ausnahmen vorbereitet ist, ist es vergleichsweise schwierig, neuen Code zu übernehmen, der Ausnahmen generiert.

Da der vorhandene Code von Google nicht ausnahmetolerant ist, sind die Kosten für die Verwendung von Ausnahmen etwas höher als die Kosten in einem neuen Projekt. Der Konvertierungsprozess wäre langsam und fehleranfällig. Wir glauben nicht, dass die verfügbaren Alternativen zu Ausnahmen wie Fehlercodes und Behauptungen eine erhebliche Belastung darstellen.

Unser Rat gegen die Verwendung von Ausnahmen basiert nicht auf philosophischen oder moralischen, sondern auf praktischen Gründen. Da wir unsere Open-Source-Projekte bei Google verwenden möchten und dies schwierig ist, wenn diese Projekte Ausnahmen verwenden, müssen wir auch bei Open-Source-Projekten von Google von Ausnahmen abraten. Die Dinge wären wahrscheinlich anders, wenn wir alles noch einmal von Grund auf neu machen müssten.

Es gibt eine Ausnahme von dieser Regel (kein Wortspiel beabsichtigt) für Windows-Code.

(Schwerpunkt des Herausgebers)

7
SuperElectric

Qt verwendet fast nie Ausnahmen. Fehler in Qt werden mit Fehlercodes und Signalen angezeigt. Der offiziell angegebene Grund ist:

Beim Start von Qt waren nicht für alle Compiler Ausnahmen verfügbar, die von Qt unterstützt werden mussten. Heute versuchen wir, die APIs konsistent zu halten, sodass Module, bei denen in der Vergangenheit keine Ausnahmen verwendet wurden, im Allgemeinen keinen neuen Code mit hinzugefügten Ausnahmen erhalten.

Warum verwendet QT so wenige Ausnahmen?

Eine verbreitete Kritik an Qt ist heute, dass seine Ausnahmesicherheit nicht vollständig ist.

5
user16764

Symbian C++ (auf einigen Nokia-Mobiltelefonen verwendet) verwendet keine Ausnahmen, zumindest nicht direkt, da C++ - Compiler diese bei der ersten Entwicklung von Symbian nicht zuverlässig implementiert haben.

4
Keith Thompson

Ich/nie/benutze 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 Flusskontrolle als für eine Fehlerbehandlung verwendet, die sehr schwer, leistungsschwach und schwer zu debuggen ist. Im Allgemeinen waren Debugging-Probleme im ausnahmegefüllten Code schwieriger als im ausnahmefreien Code - teilweise aufgrund des Stapels und der intrinsischen Schwierigkeiten des Ausnahmemechanismus, aber viel mehr als aufgrund des faulen Codes, der als empfohlen wurde Ergebnis der verfügbaren Ausnahmebehandlung.

An 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, mit Fehlern umzugehen - wie mit Ihrer eigenen Logik (es ist schwer, darauf einzugehen - es ist fast gesunder 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 haben, 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 debuggbarer, Fehlercodes sind weniger schwergewichtig. Wenn Sie sie richtig verwenden, können Sie Code schneller lesen, debuggen und warten, was schneller ist. Es gewinnt rundum ...

3
jheriko

Im Joint Strike Fighter C++ Codierungsstandard von Bjarne et. al. sind Ausnahmen aufgrund der hohen Echtzeitanforderungen von Kampfjets verboten.

JSF ++ ist für Echtzeit- und sicherheitskritische Anwendungen (Flugsteuerungssoftware) vorgesehen. Wenn eine Berechnung zu lange dauert, kann jemand sterben. Aus diesem Grund müssen wir Antwortzeiten garantieren, und wir können dies bei der derzeitigen Tool-Unterstützung nicht für Ausnahmen tun. In diesem Zusammenhang ist sogar die kostenlose Zuweisung von Filialen verboten! Tatsächlich simulieren die JSF ++ - Empfehlungen für die Fehlerbehandlung die Verwendung von Ausnahmen in Erwartung des Tages, an dem wir die Werkzeuge haben, um die Dinge richtig zu machen, d. H. Ausnahmen zu verwenden.

Zitiert aus Bjarnes C++ FAQ .

Denken Sie daran, C++ führt wahrscheinlich die größte Auswahl an Software aller Sprachen aus ...

3
Macke

Es ist wichtig für das Design von C++ - Bibliotheken. Mit einer C-Schnittstelle ist es oft unangenehm, eine Ausnahme aus Ihrer Drittanbieter-Bibliothek an den Client zu senden. Wenn Ihre Bibliothek wirft, schneiden Sie eine Reihe von Clients aus, die sie verwendet hätten, da sie eine No-Throw-Garantie hatten (aus welchem ​​Grund auch immer der Client für eine Einschränkung der Ausnahmen hat).

Persönlich habe ich Ausnahmen missbraucht gesehen, als das Team aufgefordert wurde, "eine Ausnahme zu machen", wenn etwas nicht so Schreckliches passiert. Natürlich sehen Sie den Fehler hier - die Ausnahme wurde im Code ausgelöst, bevor jemand herausgefunden hat, was damit zu tun ist. Dieses Projekt hatte einige Abstürze, da diese tiefen Würfe gelegentlich auftauchten.

2
anon

Vielleicht ist es in dieser Hinsicht erwähnenswert Embedded C++ . 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++, bei der (unter anderem) Vorlagen, Namespaces und Ausnahmebehandlungen entfernt wurden.

Ich sollte hinzufügen, dass EC++, als es neu war, zwar ein bisschen Aufsehen erregte, aber größtenteils ziemlich leise geworden zu sein scheint. 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 zu beschäftigen. <closed captioning for the humor impaired>Yeah, right!</closed captioning>

1
Jerry Coffin

Ein gutes Beispiel ist die Kernelmodus-Programmierung.

Sie können dort C++ für saubereren Code verwenden, jedoch ohne Ausnahmen. Es gibt keine Laufzeitbibliothek für sie und die Ausnahmebehandlung verwendet zu viel Stapelspeicher, der im Kernel sehr begrenzt ist (ich habe mit C++ - Ausnahmen im Windows NT-Kernel experimentiert, und das Auslösen und Abwickeln von Ausnahmen verschlingt die Hälfte des verfügbaren Stapels - sehr einfach, um einen Stapelüberlauf zu erhalten und das ganze System zum Absturz bringen).

Normalerweise definieren Sie Ihre eigenen Operatoren new und delete. Außerdem fand ich eine placement new - und eine c ++ 11-Wertreferenz ziemlich praktisch. Es können keine STL- oder andere C++ - Benutzermodusbibliotheken verwendet werden, die auf Ausnahmen beruhen.

1
Sergius

Wenn Sie versuchen, den ausführbaren Speicher niedrig zu halten. In der Regel auf eingebetteten (oder mobilen) Systemen. Für Desktops-Apps wird es nie benötigt, jedoch kann es auf Servern in Betracht gezogen werden, wenn Sie so viel RAM wie möglich für den Webserver oder für SQL benötigen.

0
user2528