7

std::uncaught_exception()デストラクタからのスローは一般的に悪い考えであることは知っていますが、デストラクタから安全にスローするために使用できるかどうか疑問に思っていました。

次の RAII タイプを検討してください。

struct RAIIType {
   ...

   ~RAIIType() {
      //do stuff..
      if (SomethingBadHappened()) {
           //Assume that if an exception is already active, we don't really need to detect this error
           if (!std::uncaught_exception()) {
               throw std::runtime_error("Data corrupted");
           }
      }
   }
};

これは c++11 の UB ですか? 悪いデザインですか?

4

4 に答える 4

4

あなたはif「その他」の状態について考えましたか?例外をスローするか...何をしますか? もう一方のブランチにできることは 2 つあります。

  • なし (エラーが発生したときに何もする必要がない場合、なぜ例外をスローするのですか?)
  • 例外を「処理」します (「処理」できる場合、なぜ例外をスローするのですか?)

このように条件付きで例外をスローする目的がないことを確認したので、残りの質問は意味がありません。しかし、ちょっとしたヒントがあります。デストラクタから例外をスローしないでください。オブジェクトが例外をスローした場合、呼び出し元のコードは通常、何らかの方法でそのオブジェクトをチェックして、例外を "処理" します。そのオブジェクトが存在しなくなった場合、通常、例外を「処理」する方法はありません。つまり、例外がスローされるべきではありません。無視されるか、プログラムがダンプ ファイルを作成して中止します。したがって、デストラクタから例外をスローしても無意味です。キャッチするのは無意味だからです。これを念頭に置いて、クラスはデストラクタがスローしないと想定し、事実上すべてのクラスがデストラクタがスローした場合にリソースをリークします。

于 2013-03-21T16:33:41.897 に答える
1

std::uncaught_exception()デストラクタからのスローは一般的に悪い考えであることは知っていますが、デストラクタから安全にスローするために使用できるかどうか疑問に思っていました。

Herb Sutterによる uncaught_exceptionsの提案をご覧になることをお勧めします。

動機

std::uncaught_exceptionAlexandrescu スタイルの ScopeGuard を実装する場合など、多くの状況で「ほぼ有用」であることが知られています。[1] 特に、デストラクタで呼び出された場合、C++ プログラマが期待することが多く、基本的に正しいのは、「このデストラクタがスタックの巻き戻し中に呼び出されている場合、uncaught_exception は true を返す」ということです。</p>

ただし、少なくとも 1998 年以降、Guru of the Week #47で文書化されているように、スタックの巻き戻し中に呼び出される可能性のあるデストラクタから推移的に呼び出されるコードは、それ自体が実際に巻き戻しの一部として呼び出されているかどうかを正しく検出できないことを意味します。例外の巻き戻しを開始すると、uncaught_exception に対して、複数のアクティブな例外がある場合でも、すべてが巻き戻しのように見えます。

...

この論文では、現在アクティブな例外の数を返す新しい関数 int を提案しています。これstd::uncaught_exceptions()は、スローまたは再スローされたがまだ処理されていないことを意味します。

このオブジェクトをアンワインドするためにデストラクタが実行されているかどうかを知りたい型は、そのコンストラクタで uncaught_exceptions をクエリし、結果を格納してから、そのデストラクタで uncaught_exceptions を再度クエリできます。結果が異なる場合、このデストラクタは、オブジェクトの構築より後にスローされた新しい例外により、スタックの巻き戻しの一部として呼び出されています。

于 2015-09-30T09:59:59.657 に答える
0

「安全に」が何を意味するかによって異なります。

これにより、デストラクタからのスローに関する問題の 1 つが回避されます。別の例外を処理するときにスタックの巻き戻し中にエラーが発生した場合、プログラムは終了しません。

ただし、その中にはまだ問題があります。

  • これらの配列がある場合、破壊をスローしてもすべてが破壊されるわけではありません。
  • 一部の例外安全イディオムは、スローしない破壊に依存しています。
  • 多くの人 (私のような) は、デストラクタがスローした場合に何が正しく破棄されるか、または正しく破棄されないかを管理するすべての規則を知っているわけではなく、クラスを安全に使用できるかどうか確信が持てません。
于 2013-03-21T16:35:51.170 に答える