3

デストラクタが例外をスローしてはならないことはわかっています。

http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.13

私は次のコードを持っています:

~a()
{
    cleanup();
}

// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
    delete p;
}

私の静的ソースコード分析では、次のようにクリーンアップ関数を呼び出す必要があると不平を言っています。

~a()
{
    try {
        cleanup();
    }
    catch(...) {
        // What to do? Print out some logging message?
    }
}

// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
    delete p;
}

関数を呼び出すたびに、デストラクタに try...catch ブロックを配置するのが良い方法かどうかはわかりません。として :

(1) クリーンアップ関数が例外をスローできる場合、何か問題が発生したことがわかります。私はそれがフェイルファストであることを好みます。つまり、システム全体をクラッシュさせ、プログラマーにデバッグさせます。

(2) try...catch ブロックの入出時にオーバーヘッドが発生する。

(3) クラスのデストラクタの周りに多くの try...catch ブロックがあり、コードが煩雑に見えます。

なぜ try...catch ブロックを配置する必要があるのでしょうか。

ありがとう。

4

6 に答える 6

3

スローしないためdelete、どちらもスローしないcleanupため、呼び出しを try-catch に入れる必要はありません。

cleanupあなたの静的分析ツールはおそらくそれを理解するのに苦労しているので、no-throw として宣言することでおそらくそれを助けることができます (推測にすぎません) 。

void cleanup() throw();
于 2009-12-07T09:36:49.320 に答える
2

たぶん、クリーンアップ機能についてより正確になる可能性があります。非常にまれな状況でのみ、cleanup() 関数は意図的に例外をスローしますか? 次に、デストラクタでケースを確実に処理する必要があります。これは、まれではありますが、例外のスローが cleanup() の予期される動作であるためです。

少なくとも、例外処理コードによって、プログラムを正常に終了できるように明確に定義された状態のままにすることができます。

それとも、 cleanup() が OutOfMemoryException や、他の場所では決して処理しない別の実行時例外などをスローする可能性があるということですか? 次に、デストラクタでの例外処理も省略します。このような異常な状況では、アプリケーションはエラー処理コードを実行できない可能性があります。このような例外であっても適切に報告または記録されるように、可能な限りのことを行う必要があります。

編集:

の実装を示したのでcleanup、ニールはすでにあなたの質問に答えています。delete pをスローしてはならないため、のデストラクタがスローしないa::cleanup限りスローしません。p

于 2009-12-07T08:48:55.517 に答える
1

確かに、問題は実際には p のデストラクタにあります。cleanup() で、あなたが言うとき

delete p;

delete 自体はスローできないため、例外は p のデストラクタから発生する必要があります。a のブロックではなく、try ブロックの使用について心配する必要があるのは、そのデストラクタにあります。

于 2009-12-07T09:07:44.507 に答える
1

基本的に、すでに例外を処理しているときに例外をスローすることは安全ではありません。

スタックの巻き戻し中にデストラクタが呼び出され、別の例外がスローされた場合、Symbian などの一部のシステムではスレッドがすぐに終了する可能性があります。コードが例外をキャッチすることを計画していたとしても、その終了は停止しません。コードは呼び出されません。例外がデストラクタをエスケープすると、スレッドは確実に終了します。

したがってtry {} catch(...) {}、デストラクタでは移植性がなく、確かに注意が必要です。

適切なアドバイスは、デストラクタなどのクリーンアップコードで例外をスローする可能性のあるコードや、' cleanup()'、' '、' 'close()などのデストラクタから呼び出される可能性のある関数を呼び出すことは決してありませんrelease_something()

元の投稿者は、try-catch のパフォーマンスについても問い合わせています。C++ 例外が採用された初期には、例外処理コードはかなり高価でした。最近では、ほぼ確実にコンパイラがゼロコストの例外を使用しています。つまり、例外がスローされなくても、実行時のパフォーマンスがコードに悪影響を与えることはありません (もちろん、プログラムのバイナリ サイズはわずかに増加します)。

于 2009-12-07T09:12:11.610 に答える
1

通常、メモリの割り当てまたは削除が原因でエラーをスローしても意味がありません。それが機能するかどうかにかかわらず、何のメリットも得られずにばかげたエラーを処理するために大量の作業を費やすことができます.

特定のケースでこれを行いたいと思うかもしれませんが、実際にはあまり行われておらず、質問がある場合は通常、デバッガーまたはより完全なインストルメンテーションを使用したいと考えています。

于 2009-12-07T09:18:54.033 に答える
0

私はこれを決して使用しませんが、例外の安全性の純粋主義者は、cleanup()関数が予期せずにスローされる可能性があると言うでしょう。したがって、このパターンは安全性を高めるためのテクニックです。

ただし、cleanup関数はそもそもスローすべきではありません。したがってcleanup()、デストラクタ自体ではなく、内部に例外処理を配置します。

于 2009-12-07T08:41:33.217 に答える