web-dev-qa-db-ja.com

C ++例外を無効にして、どのようにstd :: throw()を即座に終了させることができますか?

このC++プログラムはCGIスクリプトであり、例外を処理する必要はありません。プロセスが終了した後、パフォーマンスをわずかに向上させ、OS(Linux)にクリーンアップを処理させたいと思います。

私は標準C++ライブラリを使用しており、Perlのようにdieに任意の関数を必要とします:例外がスローされるときはいつでも。 巻き戻しせずに、または私のプロセスでさらにコードを実行します。

-fno-exceptionsはどのように機能しますか?コードにまったく問題がなく、基本的に例外のようなふりをする場合は、存在しません。しかし、私はする std :: c ++ライブラリを使用しますできる throw()?

37
unixman83

オプション#1:例外をキャッチしない。

例外は、スローまたはキャッチされない限り、それほどオーバーヘッドがありません。投げてキャッチする準備ができていない場合は、とにかく死ぬつもりなので、その時点でのパフォーマンスへの影響は軽微です。例外が処理されない場合、スタックの巻き戻しは実行されないことにも注意してください。プログラムは、スタックの巻き戻しを実行せずに単に終了します。

G ++では、実際にスローされない例外にはオーバーヘッドがほとんどないことに注意することが重要です。 G ++は、スタックを介したプログラムの実行を追跡するのに十分な追加情報、およびデストラクタを呼び出すための追加コードなどを生成します。ただし、例外が実際にスローされるまで、この追加コードやデータは使用されません。したがって、例外は有効になっているが使用されていないコードと、例外が無効になっているコード(メカニズムを問わず)のパフォーマンスに違いはありません。

オプション#2:_-fno-exceptions_を渡します。

このフラグはG ++に 2つのことを行う を指示します。

  1. STLライブラリのすべての例外処理が削除されました。スローはabort()呼び出しに置き換えられます
  2. スタックアンワインドデータとコードが削除されます。これにより、コードスペースが節約され、コンパイラーにとってレジスターの割り当てがわずかに容易になります(ただし、パフォーマンスに大きな影響があるとは思えません)。ただし、特に、例外がスローされ、ライブラリが_-fno-exceptions_コードを介してアンワインドしようとすると、アンワインドデータがないため、その時点で中止されます。

これにより、必要に応じて、すべての例外をabort() sに効果的に変換できます。ただし、throwは許可されないことに注意してください。コードに実際のthrowsまたはcatchsを指定すると、コンパイル時エラーが発生します。

オプション#3:(移植不可、非推奨!)__cxa_allocate_exceptionをフックします。

C++例外は、(特に)__cxa_allocate_exceptionおよび__cxa_throw内部ライブラリ関数を使用して実装されます。これらの関数をabort()にフックするLD_PRELOADライブラリを実装できます。

_void __cxa_allocate_exception() { abort(); }
void __cxa_throw() { abort(); }
_

警告:これは恐ろしいハックです。 x86およびx86-64で動作するはずですが、これはお勧めしません。特に、_-fno-exceptions_のように、実際にパフォーマンスが向上したり、コード領域が節約されたりすることはありません。ただし、throwsをabort() sに変換しながら、throw構文を許可します。

69
bdonlan

_-fno-exceptions_は、すべての標準ライブラリスローをstd::abort() への呼び出しに変換します。これは直接変更できない部分を処理し、残りはコードでそれらをまったく使用しないことです。

もちろん、私はあなたがこれをすることの正当化を本当に疑います。実際にスローしたときにパフォーマンスが「失われる」だけであり、言語の重要で役立つビットを捨てています。

20
GManNickG

誰かがこの質問に遭遇した場合に備えて、@ GManNickGおよび( https://stackoverflow.com/a/7249460/157344 )および@bdonlan( https: //stackoverflow.com/a/7249442/157344 )が回答で述べています。残念ながら、すべての例外処理コードを削除してすべてのスローをアボートに変換する「-fno-exception」に関する部分は間違っています。まあ-部分的に間違っています。これは、このフラグを使用して問題のライブラリ(libstdc ++ v3)をコンパイルする場合に当てはまりますが、このフラグを使用してコンパイルする独自のコードでこのライブラリを(.aまたは.soまたは.dllなどとして)使用する場合は当てはまりません。 。後者の場合、あなたのコードの例外処理コードは禁止されていますが、ライブラリ内の例外処理へのすべての呼び出しは残ります(ライブラリがコンパイルされたため[〜#〜]なし[〜#〜 ]このフラグ、例外は有効になっているため)newを使用すると、実行可能ファイル[〜#〜] [〜#〜 ]には例外処理コードがあります-唯一の違いは、catch()(コードで禁止されています)ではこれらの例外について何もできないため、すべてのスローが事実上終了することですabort()と同じですが、誰もそれをキャッチできないからです。

13
Freddie Chopin

見積もり:

このC++プログラムはCGIスクリプトです。例外を処理する必要はありません。

  • その後、しないでください。シンプル。例外は非常に早くスタックの最上位に到達します。

しかし、私はあなたがそうすることをお勧めします。そうすることは、あなたが間違っている可能性があることを考えていることを意味します。

9
Ed Heal

あなたのコードのどこにもそれらを捕まえないでください。その場合、終了ハンドラが呼び出され、プログラムが「クラッシュ」します。

1
user405725