web-dev-qa-db-ja.com

Google C ++スタイルガイドの例外なしルール。 STL?

Googleの C++スタイルガイド は、「例外を使用しません」と述べています。このスタイルでは、例外の使用に関してSTLに言及していません。 STLアロケーターは失敗する可能性があるため、コンテナーによってスローされた例外をどのように処理しますか?

  1. 彼らがSTLを使用している場合、呼び出し元は割り当ての失敗をどのように通知されますか? Push_back()やmap operator[]などのSTLメソッドは、ステータスコードを返しません。
  2. STLを使用しない場合、どのコンテナ実装を使用しますか?
65
Andrei

彼らは、theyは例外を使用しないで、誰も例外を使用してはいけないと言っています。理論的根拠を見ると、彼らも書いている:

Googleの既存のC++コードのほとんどは例外を処理する準備ができていないため、例外を生成する新しいコードを採用することは比較的困難です。

通常のレガシー問題。 :-(

53
Bo Persson

少なくともdo n'tコンテナによってスローされた例外を、少なくともアプリケーションレベルのコードで処理します。

私は2008年からC++で作業するGoogle検索のエンジニアです。STLコンテナを頻繁に使用しています。 vector :: Push_back()やmap :: operator []のような失敗にまでさかのぼる単一の大きな失敗やバグを個人的に思い出すことはできません。 「失敗」または「ダング、例外を使用した場合のみ、これは回避できたはずです。」プロセスがメモリ不足になることはありますか?はい。ただし、これは通常単純な間違いです(たとえば、誰かがプログラムに大きな新しいデータファイルを追加し、RAM割り当て)を増やすのを忘れた場合、または回復する良い方法がない致命的な障害私たちのシステムは、障害のあるディスク、宇宙線などを備えたマシンに対して堅牢になるように、すでにジョブを自動的に管理および再起動しますが、これもまったく同じです。

私が知る限り、ここで問題はありません。

42
hoffmanj

theirコードで例外を使用しないことを意味すると確信しています。 cpplint script をチェックアウトすると、STLコンテナー(ベクター、リストなど)の正しいヘッダーが含まれていることを確認します。

11
Mark Loeser

とにかく、最新のオペレーティングシステムでは割り当てエラーを処理できません。パフォーマンスの最適化として、通常はメモリをオーバーコミットします。たとえば、malloc()を呼び出してLinuxで非常に大きなメモリチャンクを要求すると、実際にバックアップに必要なメモリがなくても成功します。カーネルが実際にそれをバックアップするページを割り当てようとするのは、アクセスしたときだけであり、その時点で割り当てが失敗したと伝えるには遅すぎます。

そう:

  1. 特別な場合を除き、割り当ての失敗を心配しないでください。マシンのメモリが不足すると、それは致命的な障害になり、そこから確実に回復することはできません。

  2. それでも、未処理の例外をキャッチし、e.what()出力をログに記録してから、_throwをログに記録することをお勧めします。それはあなたのために自動的に。

  3. メモリ不足になったときにクラッシュに頼ることができないという上記の巨大なスレッドはすべて完了し、完全にゴミです。 C(++)標準では保証されない場合がありますが、現代のシステムでは、クラッシュするのはonlyであり、実行すると信頼できるものですメモリ不足。特に、アロケータからNULLまたは実際にその他の表示を取得することに依存することはできません。C++例外までは含まれません。

  4. ページ0にアクセスできる組み込みシステムを使用している場合は、その場所にアクセスできないページをマッピングすることで修正することを強くお勧めします。人間はどこにでもNULLポインターをチェックすることに依存することはできませんが、ページonceをマッピングすることで修正することができます。誰かがNULLを見逃している可能性のあるすべての(過去、現在および未来)位置を修正します。

何らかのカスタムアロケーターを使用している可能性がある、またはオーバーコミットしないシステム上にいる可能性があると言って上記を修飾します(スワップのない組み込みシステムはその一例ですが、それだけではありません例)。その場合、多分youがメモリ不足状態を適切に処理できます。システム上で。しかし、一般的に21世紀には、チャンスを得る可能性は低いと思います。システムがメモリ不足であることを最初に知るのは、物事がクラッシュし始めるときです。

6
alastair

GoogleはSTLと例外についてこれを明示的に言及していることがわかりました(強調は私のものです):

独自のコードで例外を使用するべきではありませんが、例外はATLおよび一部のSTL(Visual C++に付属するものを含む)で広く使用されています。 ATLを使用する場合、_ATL_NO_EXCEPTIONSを定義して例外を無効にする必要があります。 STLで例外を無効にできるかどうかを調査する必要がありますが、そうでない場合は、コンパイラで例外を有効にしてもかまいません。 (これは、STLをコンパイルするためだけのものです。例外処理コードを自分で書くべきではありません。

私はそのような決定は好きではありませんが(幸運なことに私はグーグルで働いていないのですが)、彼らは彼らの行動や意図についてははっきりしています。

6
Yongwei Wu

Stl自体は、メモリ割り当てが失敗した場合にのみ直接スローされます。しかし、通常、実世界のアプリケーションはさまざまな理由で失敗する可能性があり、メモリ割り当ての失敗はそのうちの1つにすぎません。 32ビットシステムでは、メモリ割り当てエラーは発生する可能性があるため、無視すべきものではありません。したがって、メモリ割り当てエラーが発生しないという上記の議論全体は、無意味なものです。これを想定しても、2段階の初期化を使用して1つのコードを記述する必要があります。また、C++の例外処理は、64ビットアーキテクチャよりも前から存在していました。ここにグーグルが示したネガティブなプロフェッショナリズムをどれだけ堂々と尊敬し、質問に答えるだけでいいのかは定かではありません。 1997年頃にIBMがC++例外処理の意味を理解し、高く評価したIBMの一部の論文を覚えています。 Okプロフェッショナリズムは必ずしも成功の指標ではありません。したがって、例外処理を放棄することは、STLを使用する場合の問題だけではありません。C++を使用する場合は問題です。

  • コンストラクターの失敗
  • 次のベース/メンバークラスコンストラクターの引数としてメンバーオブジェクトとベースクラスオブジェクトを使用できること(テストなし)。 C++例外処理が存在する前に、人々が2ステップ構成を使用したのも不思議ではありません。
  • 顧客または第三者がコードを提供してエラーをスローできる環境で、階層的で豊富なエラーメッセージをあきらめます。呼び出し元コードの元の作成者は、呼び出し元コードの作成時に予測できず、スペースを提供できた可能性があります彼のリターンエラーコードの範囲で。
  • flexLmの作成者が行ったメッセージ割り当てエラーへの静的メモリオブジェクトへのポインタを返すようなハッキングを回避します。
  • メモリマッピングされたスパースファイルにアドレスを返すメモリアロケータを使用できること。この場合、問題のメモリにアクセスすると割り当てエラーが発生します。(ok現在、これはウィンドウでのみ機能しますが、AppleはGnuコンパイラにG ++コンパイラで必要な機能を提供することを強制しました。 Linux g ++の開発者は、この機能を提供する必要があります)(おっと、これはSTLにも当てはまります)
  • このCスタイルのコーディングを残して(戻り値を無視して)、デバッグ実行可能ファイルでデバッガを使用して、サードパーティが提供する子プロセスと共有ライブラリまたはリモート実行を行う非自明な環境で何が失敗しているかを調べる必要があります
  • すべてをstderrにダンプすることなく、呼び出し元に豊富なエラー情報を返すことができる
4
user678269

質問で概説された仮定の下で、割り当ての失敗を処理する可能性は1つだけです。

  • そのアロケーターは、割り当ての失敗時にアプリケーションを強制的に終了します。特に、これにはcusrorアロケーターが必要です。

アプリケーションは事前チェックを使用して発生しないことを保証できるので、このコンテキストでは、範囲外のインデックス例外はあまり興味深いものではありません。

2
Andrei