web-dev-qa-db-ja.com

例外なく、C ++の実際のケースはありますか?

C++を介してCを使用する場合、およびC++を介してC++を使用する場合 には、ステートメントwrtがあります。コードサイズ/ C++の例外:

ジェリーの回答 (他のポイントの中で):

(...)C++で本当に小さな実行可能ファイルを生成することはより困難になる傾向があります。本当に小さなシステムでは、とにかく大量のコードを書くことはめったになく、余分な(...)

なぜそうなるのかと私は尋ねたところ、ジェリーは答えた。

主なことは、C++には例外処理が含まれているため、(少なくとも通常は)実行可能サイズに最小値が追加されます。ほとんどのコンパイラーでは、例外処理を無効にすることができますが、その場合、結果はC++にはなりません。 (...)

技術的な現実世界のレベルで私は本当に疑いません。


したがって、プロジェクトが言語としてC++を選択し、次に例外を無効にすることを選択した実例から聞いて(純粋に好奇心から)興味があります。 (単にユーザーコードで例外を「使用しない」だけでなく、例外をスローまたはキャッチできないようにコンパイラーで例外を無効にします。)プロジェクトがそうすることを選択した理由(なぜCではなくC++を使用しているが、例外)-(技術的な)理由は何ですか?


補遺:回答について詳しく説明したい場合は、例外なしの影響がどのように処理されるかを詳しく説明すると便利です。

  • STLコレクション(vector、...)が正しく機能しません(割り当てエラーを報告できません)
  • newスローできません
  • コンストラクタは失敗できません
40
Martin Ba

現在でも、ほとんどすべてのコンソールゲームはC++で例外が無効になっています事実上、これらのコンソールを対象とするC++コンパイラのデフォルトのセットアップです。多重継承など、一部のC++機能がこれらのコンパイラで正しく動作することが保証されていない場合があります(たとえば、非常によく知られたコンソールのデフォルトコンパイラについて考えています)。


また、別の例は C++で例外なくアクティブ化されるArduinoハードウェアSDKとgccを使用し、STLが提供されていないなど です。


良いか悪いかなど、いくつかの技術的な理由があります。それは私のアドバイスではなく、私が聞いた理由です。

  1. ほとんどのコンソールは、メモリと処理時間が制限された組み込みシステムです。多分それは将来のコンソールではそれほど真実ではないかもしれませんが、現在のものはまだPCと比較してかなり制限的です。一部のポータブルコンソールは、NDSなどのどのスマートフォンよりもプログラミングがかなり難しいです。例外機能を使用すると、たとえ使用しなくても、メモリが追加され、速度が少し低下します。自分でチェックできます。PCでも同じです。
  2. コンソールのビデオゲームはクラッシュできません。クラッシュや行き止まり、ショートッパーを回避する方法でテストする必要があります。そのため、コンソールメーカーは、ゲームを公開する前に厳重にチェックするように求めています。これは、コンソールゲームの場合には例外管理によってコストが増えることも意味します。たとえば、回復する方法がいくつかあるか、問題を電子メールで送信するためのコードを追加している可能性があるため、スマートフォンの方が適しています。ほとんどのコンソールのようなクローズドプラットフォームでは、これは許可されていません。結局のところ、例外システムは本当に必要ありません。あなたは「それを正しく機能させなければならない」だけです。 ;)
  3. 例外管理は、エラーとクラッシュを許可しない場合、エラー管理戦略を実装する必要があることを意味します。そのようなシステムは、誰かがそれを有用にするために多くの時間働くようにするのに十分に複雑かもしれません。ゲーム開発者は、クラッシュに役立つと思われる機能に取り組む余裕がありません...
  4. コンパイラは(まだ)それを許可しません。はい、起こります。

例外はゲームでも役立つと思いますが、コンソールゲームではそれほど便利ではないのは事実です。


更新:

ここに別の意外な例を追加します: LLVM/CLang例外を使用しないでくださいまたはRTTI以下の理由により

コードと実行可能ファイルのサイズを削減するために、LLVMはRTTI(例:dynamic_cast <>)または例外を使用しません。これら2つの言語機能は、「使用した分だけ支払う」というC++の一般原則に違反しているため、コードベースで例外が使用されない場合や、クラスでRTTIが使用されない場合でも、実行可能肥大化を引き起こします。このため、コード内でグローバルにオフにします。

そうは言っても、LLVMはisa <>、cast <>、dyn_cast <>などのテンプレートを使用するRTTIの手巻き形式を幅広く利用しています。この形式のRTTIはオプトインであり、任意のクラスに追加できます。また、dynamic_cast <>よりも大幅に効率的です。

CLangは、コンパイルの速度と明示的なエラーでよく知られていますが、非常にわかりやすいコードを持つ珍しいコンパイラーの1つでもあります。

35
Klaim

ジェリーは言った:...結果はもはや完全なC++ではありません、私の比喩はそれがis明らかにC++、プログラムは他の形式、規則、および書体を利用しているため、わずかに異なるdialectです。

これらを無効にする主な理由は次のとおりです。

バイナリ互換

言語と翻訳の境界を越えることは、普遍的に明確に定義されていない、または未定義ではありません。プログラムが定義された動作のドメイン内で動作することを保証するには、モジュールの出口点で例外を隔離する必要があります。

実行可能サイズ

以下は、私が書いた、例外なしで有効にした例外なしのプログラムのバイナリサイズです。

例外なし:

  • 実行可能ファイル+依存関係:330
  • 最終的な除去された実行可能ファイル(リリースビルド):37

例外あり:

  • 実行可能ファイル+依存関係:380
  • 最終的に除去された実行可能ファイル(リリースビルド):44

注意:スロー/キャッチがゼロのライブラリとプログラムのコレクションです。コンパイラフラグdoesは、C++標準ライブラリで例外を有効にします。したがって、この例では、現実世界のコストは19%を超えています。

コンパイラ:Apple gcc4.2 +llvm。MB単位のサイズ。

速度

「ゼロコストの例外」という用語にも関わらず、何もスローしない場合でもオーバーヘッドが追加されます。上記の場合、これはパフォーマンスが重要なプログラムです(信号処理、生成、プレゼンテーション、変換、大規模なデータセット/信号など)。この設計では例外は必須の機能ではありませんが、パフォーマンスは非常に重要です。

プログラムの正確さ

奇妙な理由のようです...スローがオプションではない場合、プログラムが正しく実行され、クライアントがインターフェイスを正しく使用することを保証するために、比較的厳格で正確な十分にテストされたプログラムを書く必要がありますエラーコードを確認しないと、UBに値します)。結果?実装品質が大幅に向上し、問題がすばやく修正されます。

シンプル

例外処理の実装は、しばしば最新の状態に保たれていません。また、実装には非常に多くの終了シーケンスが含まれる可能性があるため、複雑さが増します。高度に定義され、型指定された出口戦略の小さなセットを使用する場合、非常に複雑なプログラムを読み取って維持する方が簡単です。他の場合では、実装は時間の経過とともにより多くのスローを実装するか、それらの依存関係がそれらを導入する可能性があります。クライアントは、これらのすべての出口を簡単または適切に防御することはできません。たくさんのライブラリを書いて更新していますが、進化と改善は頻繁にあります。すべてを(大きなコードベースの)例外の終了シーケンスと同期させようとすることは、時間の有効な使用とはならず、多くのノイズとノイズを追加する可能性があります。プログラムの正確性の向上とテストの増加により、潜在的な問題/出口の多く(すべてではない)が除外される可能性があります。

履歴/既存のコード

場合によっては、歴史的な理由で導入されなかったことがあります。既存のコードベースはそれらを使用せず、プログラムの変更には数年かかる可能性があり、規則と実装のオーバーラップのために維持するのが非常に醜くなります。

欠点

もちろん、欠点もあります。最大のものは、他のライブラリーとの非互換性(バイナリーを含む)と、このモデルに適合するために大量のプログラムを実装する必要があるという事実です。

9
justin

Googleは C++ Style Guide の例外を承認しません。これは主に歴史的な理由によるものです。

特に、新しいプロジェクトでは、例外を使用するメリットがコストを上回ります。ただし、既存のコードの場合、例外の導入はすべての依存コードに影響を及ぼします。例外が新しいプロジェクトを超えて伝播される可能性がある場合、新しいプロジェクトを既存の例外のないコードに統合することも問題になります。 Googleの既存のC++コードのほとんどは例外を処理する準備ができていないため、例外を生成する新しいコードを採用することは比較的困難です。

Googleの既存のコードは例外に対応できないため、例外を使用するコストは、新しいプロジェクトのコストよりもいくらか高くなります。変換プロセスは遅く、エラーが発生しやすくなります。エラーコードやアサーションなどの例外の代替案が大きな負担になるとは考えていません。

例外の使用に対する私たちのアドバイスは、哲学的または道徳的な根拠に基づくものではなく、実際的な根拠に基づいています。 Googleでオープンソースプロジェクトを使用したいので、それらのプロジェクトで例外を使用するのは難しいので、Googleオープンソースプロジェクトでも例外に対してアドバイスする必要があります。 最初からやり直す必要がある場合、状況はおそらく異なるでしょう。

Windowsコードの場合、この規則には例外があります(しゃれはありません)。

(編集者の強調)

7
SuperElectric

Qtが例外を使用することはほとんどありません。 Qtのエラーは、エラーコードとシグナルで示されます。公式に述べられた理由は次のとおりです:

Qtの起動時に、Qtでサポートする必要があるすべてのコンパイラで例外を使用できませんでした。今日、APIの一貫性を保つように努めているため、例外を使用していない履歴があるモジュールは、通常、追加された例外を使用して新しいコードを取得しません。

QTが例外をほとんど使用しないのはなぜですか?

今日、Qtに対する1つの一般的な批判は、その 例外安全 が完全ではないということです。

5
user16764

Symbian C++(一部のNokia携帯電話で使用)は、Symbianが最初に開発されたときにC++コンパイラが例外を確実に実装していなかったため、少なくとも直接は例外を使用していません。

4
Keith Thompson

私は例外を/決して/使用しません。これにはいくつかの理由がありますが、2つの主な理由は、堅牢なコードを生成するためにそれらを必要としたことがないことと、実行時のパフォーマンスを低下させることです。

私は例外を使用して無効にするプロダクションコードに取り組んできました-例外を許可するコードは一様に悪いものでした。一部の場所では、例外がエラー処理ではなく本物のフロー制御に使用されていました。これは非常に重く、パフォーマンスが低く、デバッグが困難です。一般に、例外が満たされたコードのデバッグ問題は、例外のないコードよりも困難でした。一部にはスタックと例外メカニズムの本質的な問題がありましたが、それ以上に、遅延コードが推奨されていました。例外処理を利用できるようにした結果。

例外自体に深刻な問題はありません/パフォーマンスを気にしない場合/適切に何かをする時間がない場合-これらはエラー処理の言語機能であり、適切なエラー処理メカニズムの優れた代替品です。ただし、エラーを処理する方法はほとんど常に/ better /です。たとえば、独自のロジックの場合と同様です(これについて詳しく説明するのは難しいので、常識です)。エラーではなく、ライブラリ(標準ライブラリなど)からのものである場合は、例外の選択を尊重するか、クラッシュする必要がありますが、その選択については常に質問します。例外が実際に最善の解決策である状況を見たことがありません。

アサーションはよりデバッグ可能で、エラーコードはそれほど重要ではありません... 2つの間で適切に使用すると、コードの読み取り、デバッグ、および保守がより簡単になり、高速になります。そのすべてが勝つ...

3
jheriko

Bjarneらによる Joint Strike Fighter C++コーディング標準 でまた、戦闘機の厳しいリアルタイム要件のため、例外は禁止されています。

JSF ++は、ハードリアルタイムで安全性が重要なアプリケーション(飛行制御ソフトウェア)用です。計算に時間がかかりすぎると、誰かが死ぬ可能性があります。そのため、応答時間を保証する必要があります。現在のレベルのツールサポートでは、例外に対してこれを行うことはできません。その文脈では、無料の店舗割り当てさえ禁止されています!実際、エラー処理に関するJSF ++の推奨事項は、例外を使用するなど、正しく機能するツールがある日を見越して、例外の使用をシミュレートします。

BjarneのC++ FAQ から引用。

覚えておいてください、C++はおそらくすべての言語の最も幅広いソフトウェアを実行します...

3
Macke

これは、C++ライブラリの設計で重要です。多くの場合、Cインターフェースでは、サードパーティのライブラリからクライアントに例外をスローするのは一種の厄介です。ポイントは、ライブラリがスローすると、(例外の制限のためにクライアントが何らかの理由で)スローしないことが保証されていれば、それを使用したであろうクライアントのセットを切り捨てているということです。

個人的に、それほどひどくないことが起こったときにチームが「例外をスローする」ように指示されたときに、例外が悪用されるのを見てきました。もちろん、ここでエラーが表示されます-例外は、誰がそれをどうするかを理解する前にコードでスローされました。これらのディープスローが時折発生するため、このプロジェクトにはいくつかのクラッシュがありました。

2
anon

おそらくこれに関して、言及する価値があります Embedded C++ 。組み込みC++は、組み込みシステム用に設計された(明らかに十分な)C++のバリアントです。これは基本的にC++の適切なサブセットであり、(とりわけ)テンプレート、名前空間、および例外処理が削除されています。

EC++が新しいときに少しはねたが、かなり静かになっているようだ。人々が興味を失ったのか、それとも彼らの最初の試みが単に完璧だったのか、10年ほどの間それをいじる理由を誰も見なかったのかどうか、私にはわかりません。 <closed captioning for the humor impaired>Yeah, right!</closed captioning>

1
Jerry Coffin

良い例は、カーネルモードプログラミングです。

そこで、C++を使用してコードをより簡潔にすることができますが、例外はありません。それらのランタイムライブラリはなく、例外処理はカーネルで非常に制限されたスタックメモリを使用しすぎます(Windows NTカーネルでC++例外を試してみましたが、例外のスローとアンワインドは利用可能なスタックの半分を消費します-スタックオーバーフローを取得するのは非常に簡単ですシステム全体をクラッシュさせます)。

通常は、独自のnewおよびdelete演算子を定義します。また、かなり便利なplacement newおよびc ++ 11右辺値参照。例外に依存するSTLまたはその他のC++ユーザーモードライブラリは使用できません。

1
Sergius

実行可能メモリを抑えようとしているとき。通常、組み込み(またはモバイル)システムで行われます。デスクトップアプリの場合は必要ありませんが、サーバーでは、WebサーバーまたはSQLにできるだけ多くのRAMが必要かどうかを検討することができます。

0
user2528