例外のないC ++の実際のケースはありますか?[閉まっている]


40

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

ジェリーの回答(他の点の中でも):

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

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

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

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


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


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

  • STLコレクション(vector、...)は正常に動作しません(割り当てエラーは報告できません)
  • new 投げられない
  • コンストラクターが失敗することはありません

1
JSF C ++。ジェットと例外は混在しません。
コーダー

1
例外(およびC ++全般)の問題に関するいくつかの啓発的な情報250bpm.com/blog:4
Ambroz Bizjak

1
@AmbrozBizjak-リンク先の投稿へのコメントからDeadMGを引用します。quote:「例外を理解していないようです。」同意する。著者は明らかに彼がその投稿で与える例を見て、例外処理の混乱を作りました。
マーティンBa

回答:


35

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


また、別の例は、C ++でアクティブ化された例外なくgccを使用するArduinoハードウェアSDKや、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は、コンパイル速度と明示的なエラーの速度でよく知られていますが、非常にわかりやすいコードを持つ、まれなコンパイラでもあります。


9
(3):(2)を使用する場合は、何があってもエラー管理戦略が必要です。問題が発生し、コンソールソフトウェアはソフトで正常に失敗する必要があります。例外を完全に回避することでそれが容易になることは私には明らかではありません。
デヴィッドソーンリー

6
エラーが適切に処理され、「例外的な」イベントがない、厳密に制御されたランタイム環境のすべての素晴らしい例。
パトリック・ヒューズ

1
@DavidThornleyコンソールのシステムが何らかのエラーを管理すると想定しているが、そうではないためです。PS3またはXBoxで動作するかもしれませんが、コンソールビルダーのテストに合格することはできません。とにかく、ほとんどの高度なコンソールのファームウェアはあなたが思うほど柔軟ではありません。コンソールゲームは、コンソールのほぼすべてのハードウェアにアクセスする必要があるため、コンソールで実行されているゲームを、コンソールの「OS」でもあるかのように考えることができます。それは真実ではありません。ですから、場合によっては奇妙に思えることに同意します。
クライム

2
これは良い答えです。例外が発生してユーザーにエラーが表示された場合でも、D-padでそれをどうするかを追加したいと思います。エンドユーザーにとって唯一の現実的なソリューションは、再起動です。
アノン

2
チームの誰かがブーストでNO EXCEPTIONを「例外の使用なし」ではなく「ルールの例外なし」を意味するものではないと言ったので、私は愚かな例を削除しました。参照してくださいpermalink.gmane.org/gmane.comp.lib.boost.devel/231377
Klaim

9

Jerry氏:...結果はもうC ++ではありませんが、私の比phor 明らかにC ++であり、プログラムが他の形式、規則、書かれたスタイルを利用しているため、わずかに異なる方言であるということです。

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

バイナリ互換性

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

実行可能サイズ

以下は、例外を有効にした場合と無効にしない場合に作成した、例外を含まないプログラムのバイナリサイズです。

例外なし:

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

例外あり:

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

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

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

速度

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

プログラムの正確さ

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

シンプルさ

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

履歴/既存のコード

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

欠点

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


+1優れた情報!(私はシンプルさのパラグラフに同意しませんが)
マーティンBa

失敗しないコンストラクターと割り当ての処理方法(-失敗)だけがある場合は興味深いでしょう。
マーティンBa

@Martin 1)意見の相違はまったく問題ありません。ほとんどの開発者は、複数の理由で例外を無効にすることに同意しないことを理解しています。簡単にするために、プログラムの正確性も考慮しています。問題/無効な状態は単純に遠くまで移動することはできません。つまり、障害をチェックして正常に終了します。jherikoの投稿はこれを反映しています。
ジャスティン

1
@Martin 2b)割り当てはもう少し複雑です。まず、ヒープ割り当ての数が減り、サイズが大きくなります-開始するヒープ割り当ては比較的少ないです。第二に、割り当てはカスタムアロケータを経由します。アロケーターに割り当てが最初に提供されなかった場合(例:をmalloc返す0)、アロケーターはwhile (1)コンテキスト切り替えのあるを入力し、その後に割り当ての別の試行が続きます。このコードベースでは、以前はアロケータを介したnewが0を返すことができましたが、新しい実装では問題なく動作していました。(続き)
ジャスティン

2
はい、カスタムアロケーターインターフェイス上にstl互換のラッパーがあります。技術的には、プログラムはリリース時に中断しません。コンテキストスイッチを導入し(たとえば、別のスレッドがメモリを解放できるように動作させる)、再試行し、失敗した場合はログに記録します-永久に。単体テストは問題なく数日間実行できます。唯一の本当の脅威は巨大な割り当てであり、その多くは要求される前にキャッチされます。この場合も、システムの故障率はこの時点でレーダー上にあります。そのようなシナリオでは、コア実装の前に失敗する可能性があります。
ジャスティン

7

Googleは、主に歴史的な理由により、C ++ Style Guideの例外を承認していません。

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

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

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

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

(編集者の強調)


5

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

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

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

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


1
ありがとう。私はほとんどのQTのコードベースは、おそらく例外が...コンパイラで有効になっているかどうか迷っていますが、情報グッド
マーティンのBa

4

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


1
これは、Symbianの最新バージョンには当てはまりません。Symbian TRAPとリーフは実際のC ++例外として実装されていますが、EPOC32とSymbianの古いバージョンは他の手段(正しく思い出せばsetjmp / longjmp)に依存していました。
オットー

1
@OttoHarju:それは「少なくとも直接ではない」という意味です。
キーストンプソン

3

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

私は、例外を使用および無効化する実稼働コードに取り組んでいます-例外を許可するコードは一様に悪かったです。一部の場所では、エラー処理ではなく、純粋なフロー制御に例外が使用されていました。これは非常に重く、パフォーマンスが低く、デバッグが困難です。一般的に、例外が埋め込まれたコードのデバッグ問題は、例外のないコードよりも困難でした-部分的にはスタックと例外メカニズムの本質的な難しさまで、しかしそれよりもはるかにそれは遅延コードとして奨励されたためです例外処理が利用可能になった結果。

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

アサーションはよりデバッグしやすく、エラーコードはより軽量です。2つの間で、適切に使用すると、コードの読み取り、デバッグ、および保守が容易になり、より高速になります。そのすべての勝利...


1
いや。例外を誤用するのは簡単ですが、それ以外の例外はうまく機能します。すべての関数が例外に対して安全であれば(少なくとも通常はすべてのリソースにRTTIを使用するだけで、とにかく行う必要があります)、少なくとも同じくらい簡単に推論できます。エラーコードを適切に実行するのは非常に面倒であり、プログラムをエラー処理コードの山に埋めることになります。その場合、例外が優れています。覚えておいて、あなたとは違うことをすることは、私が正しいことをすることを気にしないという決定的な証拠ではありません。
デヴィッドソーンリー

...なぜRTTIが悪いのか、それはまったく別の話です-私が見たすべてのコンパイラに組み込まれているRTTIは、RTTIが必要な場合でも簡単に打ち負かすことができます。しかし、コンテキストに関するすべて-RTTIや例外などのこれらのことは、RADやエンタープライズアプリに最適です-ハイパフォーマンス(ゲームなど)コンピューティングの世界には場所がありません。私は...彼らはオフにすることができたすべてのターゲットにいずれかを使用して生産のゲームエンジンを見たことがない
jheriko

2
すみません-RAIIは私が意図したものです。あなたがそれを使わないなら、例外だけが台無しになるだろう。(ただし、ダイナミックキャストは私の作品では非常にうまく機能します。パフォーマンスに注意する必要があります。)
デイヴィッドソーンリー

興味深いトピック:例外により、より簡潔なエラー処理コーディングが可能になると思いますが、エラーコードは、エラーをローカルで処理できるため、より堅牢です(呼び出し元ですぐに戻りコードを確認でき、例外はキャッチされる前に呼び出しスタックをバブルアップできます)また、キャッチされない場合があり、クラッシュを引き起こします。catch(...)を使用しない限り)。
ジョルジオ

3

ジョイントストライクファイターC ++コーディング標準 Bjarneらによる。また、戦闘機の厳しいリアルタイム要件のため、例外は禁止されています。

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

BjarneのC ++ FAQから引用。

C ++は、おそらくすべての言語の最も多様なソフトウェアを実行することを忘れないでください...


JSF ++は、「新規」(新規配置以外)および「削除」の使用も禁止しています。これは、「例外なく新しい失敗をどのように処理するか」という質問の一部に対する1つの答えです
...-armb

@armb:はい。「そのコンテキストでは、無料のストア割り当ても禁止されています!」を参照してください。上記。
マッケ

2

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

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


1

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

付け加えておくと、EC ++は新しくなったときは少しはねましたが、ほとんど静かになったようです。人々が興味を失ったのか、それとも最初の試みが完璧だったのかはわかりません。<closed captioning for the humor impaired>Yeah, right!</closed captioning>


Q&Aを見る-caravan.net/ec2plus/question.html-それはほとんど死んでいると思います。
マーティンBa

1

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

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

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


0

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.