質問
と答える人は多いでしょう ない 例外がスローされ、デストラクタ-その結果が未定義です。Stroustrupの点 "ベクトルのデストラクタを呼び出しで明示的にはデストラクタの各要素になります。この場合は要素のデストラクタースローを、ベクトルの破壊に失敗した...ものはないでしを保護するスローされる例外からdestructorsので、図書館を保証するものではありませんが、要素のデストラクタはげ"(Appendix E3.2).
この記事 そう言いなが投げdestructorsておりませていただきます。
その後、私の質問は、この場を投げからデストラクタの結果は未定義の動作にどんな取り扱いはエラー発生時のデストラクタ?
エラーが発生した場合は、清掃活動だけを無視するのですか?のようにしているとエラーが表示される可能性のある取り扱いをスタックがないのデストラクタになったんだと思いまして例外をスローするのは、デストラクタ?
明らかにこれらの種類の誤差が少ないものの、可能です。
解決
例外のデストラクタは危険です。
この場合の例外では既に伝播するアプリケーションを終了させます。
#include <iostream>
class Bad
{
public:
// Added the noexcept(false) so the code keeps its original meaning.
// Post C++11 destructors are by default `noexcept(true)` and
// this will (by default) call terminate if an exception is
// escapes the destructor.
//
// But this example is designed to show that terminate is called
// if two exceptions are propagating at the same time.
~Bad() noexcept(false)
{
throw 1;
}
};
class Bad2
{
public:
~Bad2()
{
throw 1;
}
};
int main(int argc, char* argv[])
{
try
{
Bad bad;
}
catch(...)
{
std::cout << "Print This\n";
}
try
{
if (argc > 3)
{
Bad bad; // This destructor will throw an exception that escapes (see above)
throw 2; // But having two exceptions propagating at the
// same time causes terminate to be called.
}
else
{
Bad2 bad; // The exception in this destructor will
// cause terminate to be called.
}
}
catch(...)
{
std::cout << "Never print this\n";
}
}
これは基本的に突き詰めれば:
も危な(ることが例外をスローすべき公開の方法は必ずしも直接).ユーザのクラスがその潜在的に取り扱い状況が発生した場合の公開方法でキャッチし、潜在的な例外をスローしました。
のデストラクタの次のオブジェクトを呼び出しこれらの方法の場合、ユーザーが持っていなかったように明示的にも例外をスローして挟まれ-巻き込まれ落とした後を固定の問題)。
な効果をお渡ししますので責任をユーザーです。ユーザの場合は正しい例外では手動で通話の適切な機能とプロセスのエラー.ユーザの場合、オブジェクトになって、オブジェクトを破壊する)そのデストラクタは左か。
例:
std::fstream
はclose()す可能性のある例外をスローします。のデストラクタ電話ありが発生した場合は、下のファイルを開いたのがこの例外をいいを伝搬のデストラクタ.
ここでは、ユーザーのファイルオブジェクトしたい、特別な取り扱いのための問題点を閉鎖するとファイルも手動で呼びclose()は、対応できることができます。場合のいずにそのデストラクタに対応します。
スコットマイヤーズかれた記事の著書"は有効なC++"
編集:
どうやらもの"より効果的なC++"
項目11:防止のたから例外がスローされる場合出destructors
他のヒント
投げのデストラクタでクラッシュは、このデストラクタをベースとして取り入れている一環としての"巻き戻しをスタック".スタックの巻き戻し手続きる場合例外がスローされます。この過程において、すべてのオブジェクトに押し出し、スタックから"チャレンジする"という"では、例外がスローされるまで、停止->そのdestructorsが呼び出されます。この手続きは別の例外をスローすことはできません。でないコントロール可能な領域で二つの例外は、このように、これを引き起電話でabort()は、プログラムがクラッシュの制御が戻りつつある。
い との差別化 この際以下の 一般 アドバイス 特定の 例。
なお、以下の 無視 の容器オブジェクトなどの複数のd'tors物体内部の器。(で無視される一部としてオブジェクトに対してだけでなバッグに入れます。)
全体の問題となりやすいた時分割授業をするものと位置付けられる。クラスdtorできるという責務:
- (R)リリース論(通称無料とメモリ)
- (C) コミット 意味論(通称 フラッシュ ファイルをディスク)
またビューのこのように、そしてると思いるとの説がある(R)セマンティクスなどが原因の例外からdtorとしてあるものではありませんし、b)フレー-資源事業な提供のためのエラーチェックなど void
free(void* p);
.
オブジェクト(C)セマンティクスのようにファイルオブジェクトのニーズに成功しフラッシュでデータ("対象範囲守られた"データベース接続のことはコミットのdtorの異なる種類:ま ができ なんとかしなければならないエラーのアプリケーション-レベル)といい続けてしまった。
した場合のrau-α(ルートをオブジェクトとして(C)の意味にd'torsと思いそのものが奇数の場合などd'torsスローされる可能性があります.したがってき入れないでこのようなオブジェクトコンテナへでも、プログラムで terminate()
場合は、コミット-dtorげながらも例外で活躍しました。
についての誤りについてのコミット/ロールバックはセマンティクスと例外が良い話を一つの アAlexandrescu: エラー処理のC++/宣言的制御の流れ (開催 NDC2014)
の詳細、彼は説明してどのように愚図書館を実装して UncaughtExceptionCounter
その ScopeGuard
最適。
(Iあることに注意しなければ その他 また類似のアイデア)
ながら、話題にな焦点を投げからd'torするというツールを利用できる 今日の くの 問題が投げ d'tor.
の 将来, あり 月 する標準機能で、この 見 N3614, や 議論で.
Upd'17:C++17std機能です std::uncaught_exceptions
afaikt.んを迅速に見積もりのcppref記事:
注記
この例で
int
-帰国uncaught_exceptions
はは---...第 を作成しguardオブジェクト記録の数は例外をキャッチされたと見なされ そのコンストラクタです。出力は、ガードオブジェクトの デストラクタなfoo()投(その場合のキャッチされたと見なされ 例外は、デストラクタのようにコンストラクタ 観)
現実の問題を自分自身に尋ねを投げからデストラクタは、"何ができるので、呼び出し側がいいの?" が実際に使用頻度の高いものを取り揃えできないので、オフセットの危険作を投げからデストラクタ?
または破棄します Foo
オブジェクトの Foo
デストラクタ投げ出し、何ができるかを見ますか?私はログインできるので、してやっていたので無視されます。ることはありません。できない"固定"で、 Foo
オブジェクトはいない。ベストの場合、ログの例外を継続していれば何事もなかったかのように(または終了プログラムを実施しています。はかかるが未定義の動作による投げからデストラクタ?
その危険をもたな意味から読みやすさ/コード般の視点から
そのままおはこの状況
int foo()
{
Object o;
// As foo exits, o's destructor is called
}
何をすべきは例外をキャッチし、この例外?う、呼び出し側のfoo?はfooこともあります。なぜ、呼び出し側のfooケアの一部について内部オブジェクトfoo?がある場合がございますの言語を定義するこえないときは、読み取り時に、分かりにくい。
このメモリのためのオブジェクト。のメモリのオブジェクトの所有でしょうか。まだまだ割り当て(奴隷ので、デストラクタに失敗した)?考えても、オブジェクトでした スタックスペース, であったにもかかわらず
そしてこのことを考える場合
class Object
{
Object2 obj2;
Object3* obj3;
virtual ~Object()
{
// What should happen when this fails? How would I actually destroy this?
delete obj3;
// obj 2 fails to destruct when it goes out of scope, now what!?!?
// should the exception propogate?
}
};
時に削除obj3合、どうやって実際に削除する保証はなくならない?その記憶dammit!
を検討してください。にコードスニペットオブジェクトが離れて自動的にそのスタックがObject3のヒープ.以降のポインタObject3ってい種類のプールがあります。お持ちのメモリリークを引き起こします。
今一つ安全なものは以下の
class Socket
{
virtual ~Socket()
{
try
{
Close();
}
catch (...)
{
// Why did close fail? make sure it *really* does close here
}
}
};
まこの FAQ
からのISO案のためのC++(ISO/IEC JTC1/SC22N4411)
でdestructorsべきだという伝搬のデストラクタ.
3の工程の呼び出しdestructors自動オブジェに建設されたパスからtryブロックへの投入 表現を"巻き戻しをスタック." 【ご注意:場合デストラクタの実行時に呼び出されスタックの巻き戻し終了と 例外は、std::終了するという(15.5.1).でdestructorsべきだという その伝播のデストラクタ. 末注意】
おデストラクタが実行内チェーンのその他のdestructors.例外をスローすることになってお呼び出し側で複数のオブジェクトに矛盾した状態で、そのものの問題を無視し、エラーの清掃。
それは誰もがいていた投destructorsはひどい...何ができるだけているのでしょうか?だって操作が失敗する場合があり、我々の方法を実行するの清掃活動やスローされる可能性があります任意の例外をスローしました。ほとんどの場合、ユーザーを無視します。ユーザがモニターしたいの成功/失敗を浄化するようになってからの明示的な清掃日常的に見られる。
例えば:
class TempFile {
public:
TempFile(); // throws if the file couldn't be created
~TempFile() throw(); // does nothing if close() was already called; never throws
void close(); // throws if the file couldn't be deleted (e.g. file is open by another process)
// the rest of the class omitted...
};
としての回答を用いて、包括的かつ正確に、より一言だけ申し上げたいと思いつつ、規格な基準にいうと、"投げる例外destructorsいます
記事をライン"の代替投例外"リストを表示一部の問題それぞれの選択肢.そのについて報告することができな問題は無料で代替しているのに投げることができます。
トラブルはあるのでリストの選択肢はどこにも近くどを除き行動を、いっしょうし、"未定義の行動のプログラム"がある。の著者の反対に"美醜い"および"を促し悪した。今はいいですか?プログラムの悪いスタイル、ある展示未定義の動作?
私のグループを考慮し、"scopedガード"パターン投げのデストラクタの有用な多くの状況により、特にユニット。わってしまうので注意してくださC++11日を投入デストラクタの結果を呼び出 std::terminate
以来、destructorsは、暗黙のうちに含 noexcept
.
Andrzej Krzemieńskiの良いポストにdestructorsる投:
そういう視点C++11機構のデフォルトのオーバーライド noexcept
のためのdestructors:
C++11、デストラクタは暗黙的に指定し
noexcept
.を追加した場合でも無い仕様で定義するデストラクタのようになります:class MyType { public: ~MyType() { throw Exception(); } // ... };
のコンパイラがえの追加仕様
noexcept
おデストラクタ.この瞬間におデストラクタが例外をスローし,std::terminate
するというものがなかった場合はダブルの例外状態です。いう決定が正確ではないことにご注意願destructorsを投げするこの明示的にいつのオプション:
- 明示的にご指定はデストラクタとして
noexcept(false)
,- 継承クラスからもうすでに指定し、そのデストラクタとして
noexcept(false)
.- 入非静的データメンバクラスで指定し、そのデストラクタとして
noexcept(false)
.
最後に、いう、デストラクタは、必ず意識し、リスクにダブルディグリー-例外(投げながら、スタックでおくつろぎいます。このよう呼 std::terminate
でないと考えている。これを避けるために行動できないことを確認済み例外を前に、どんなふうに使 std::uncaught_exception()
.
Q:その後、私の質問は、この場合- 投げからデストラクタの結果 未定義の動作をどのように取り扱っていま エラー発生時のデストラクタ?
A:いくつかのオプション:
の例外流出のデストラクタを問わずかしいです。そこはも恐ろし)std::停止があります。
なのだが、ほかの例外流出のデストラクタ.する書き込みログは、大きな赤い悪い場合にテキストできます。
私の旧政府議事堂 :の場合
std::uncaught_exception
falseを返す場合、または例外が流れます。場合にtrueを返すと、そして秋にはログインです。
でも、それで良い投d'tors?
同意したものを投げは避けるにはデストラクタです。もうけられることがありまちの切れを受け入れることで手に入れできるようになります。いい選べる3。
が奇数の場合、実際に アイデアしだいで素晴らしい 投げからデストラクタ.のように"必要"にチェックエラーコード。この値型であるから返される機能です。場合は、呼び出し側を読み込み/チェックに含まれるエラーコードの戻り値destructs黙々と.が, 場合、返されるエラーコードは読み取りに時間の戻り値の範囲をスローします一部の例外 からそのデストラクタ.
私は現在の考え方"に従ってください(こくさい)する授業なの積極的な例外をスローからdestructorsその代わり、様の"閉じる"を行う方法を実行される処理が失敗する可能性があ...
も---と思っていdestructorsコンテナタイプの授業のようにベクターすべきではないマスクにスローされる例外からの授業が含まれている.この場合、実際に使用の"無料/閉じる"方法と通話そのものを再帰的に.あたように再帰的に.さまざまなことない狂気。例外伝搬に依存してあるスタック:ばらに生えているという例外が発生し、その後も、残りのdestructorsも運行中例外を伝播のルーチンを返しますである。複数ある場合には例外が発生し、それによってコンパイラ)のいずれかの最初の例外伝播のプログラムを終了するませていただきます。その場合多くの例外が発生することを再帰溢れるスタックそのものがあるが、間違った、誰かにいつでも大丈夫です。個人的には、errの誤差を吹き上げるよりも、隠れた秘密は、陰湿な.
ポイントは、コンテナ増加などがネガティブな要因であり、することにより、含有の授業か否かを決定する行動やぞについて投げから例外がスローされる場合そのdestructors.
マーティンBa(上)が、き建築家たちにリリースとコミットの論理です。
リリース:
きを食べます。までのメモリの解放、閉接続等誰もいないのシステムは今見ても、まだ返資源の重点が移りつつある。いように必要な実際のエラー処理ここでは、それに伴う設計上の欠陥にオブジェクトモデルです。
のためのコミット:
ここではそのままにして同じような機は、既販の"ラッパーオブジェクトのようなstd::lock_guard提供のためのミューテックス.それだけのコミットの論理にdtor。する専用のAPIは、その中でも、ラッパーオブジェクトまrau-α(コミットできるように心がけていdtors取り扱いを誤差があります。この聞き取ることができると思い例外は、デストラクタは、イブレア城、イブレア大;その発行うことになる危機的である。このメントを実装する政策と異なるエラー処理だけで建物の異なるラッパーなどstd::unique_lock前std::lock_guard、確保さんのコミットジには、半も揃えていdtorの1。
設定アラームイベントです。通常のアラームイベントをより使いやすいフォームの通知障害を浄化物
コンストラクタとは異なり、例外を投げる方法として大変有益なものであることを示オブジェクトを生成に成功し、例外はスローされるdestructors.
の問題が生じた場合、例外がスローされますからデストラクタのスタックの巻き戻します。その場合は、コンパイラを入れ状況になるかどうかを続けるスタックの巻き戻しの過程又は取扱いの新しい例外です。このため、プログラムを終了します。
その結果、キャニオンズのみなかみベースの行動は控え用の特例destructorsます。メッセージを書き込むログファイルです。
その後、私の質問は、この場を投げからデストラクタの結果 未定義の動作にどんな取り扱いはエラー発生時の デストラクタ?
主な問題は、この:できません 失敗を失敗.ということとはないだろうかが犯の取引データベースへの失敗、失敗した場合に失敗(不ンデックス)はどうなるの健全性のデータはもらえますか?
以来、destructors起動し、通常の例外的なパス、それら自体にして報告しなければなりません。かい"な失敗".
これは概念的には難しい問題がしばしばこのセクションだけでなるべくそれに失敗するとして報告しなければなりません。.例えば、データベースが書き変更前における外部データ構造またはファイルです。場合には取引に失敗した場合、そのファイル/データ構造で和えます。すべてのものを確保する為に変化する外部構成ファイルは原子の取引ができな失敗します。
の実践的な解決にはそしておそらくちょうどこのチャンス 失敗を失敗して騰詐、ものづくり 不可能な失敗できるほとんど不可能な場合があります。
最適な解決策というのははっきり書き非清掃活動ロジックになるの清掃活動ロジックできな失敗します。例えば、いく新しいデータ構造のための清掃、既存のデータ構造、そしてそれを創造することを求める補助構造を事前にいなくなってホームページを作成いたします。内のデストラクタ.
これらはすべてくれは"言うは易く行うは難し,確かに、その適切な方法を見て行きます。時には思いがあってしかるべきだと思うを書く能力別々のデストラクタ論理のための通常の実行パスから格別のものであdestructors感じる少ないダブルの責任によっても(例えば範囲の警備員を必要とする明示的な解雇;なくなりはしないが必要な場合にその差別化を例外的な破壊パスから格別。
まだ究極の問題はできませんので失敗は失敗すべきと思うかもしれないが、ハード概念設計の問題を完璧にあります。では楽になれば得られないときには、いくつかのものを包み込む複雑な制御構造のトンの気遣物相互作用ではなく、モデルデザインなど若干bulkierファッション(例:粒子システムのデストラクタは破棄の全体粒子システムではなく、別の非自明なデストラクタ一粒子).モデリングする場合は、デザイナーのこのような粗レベルは、少ない非自明なdestructorsへの対応もよくないメモリの処理費が必要だdestructorsして報告しなければなりません。.
この最も簡単な解決に自然に使用destructors少なの粒子とえば、なにを破壊し取り付けたり取り外したりすると、粒子のアトラクションは時代とともにすべきことなり失敗するかもしれませんものとします。その場合は、代わりにを呼び出しなどのロジックを通じて、素粒子のdtorる実行される可能性があります。に例外的なパスが代わりについてすべての粒子システムで 削除し 粒子.脱粒子が常に理解してもらうように非特ます。の場合はシステムが破壊されなかにはできるだけでパージすべての粒子が、まぁいいんじゃない個々の粒子除去の論理に失敗する、という論理に失敗するだけ実行中の粒子システムの通常の実行時の除去が一つ以上の粒です。
を受けることがしばしのようにソリューションを作を避けた場合、対応も気遣オブジェクト非自明なdestructors.ですが絡まってしって散乱がそうではほぼ不可能にする例外では安全だが絡まってし盛りだくさんの気遣オブジェクトを全て自明ではないdtors.
でバランスを再構築することが多くの場合nothrow/noexcept実際に翻訳コンパイラエラーの場合もある指定を含む仮想機能を継承し、noexcept仕様の基底クラス)を試みたを呼び出すというスロー.このように私たちはあなたに追いつくことができこんでコンパイル時また実際に書デストラクタの無意識がスロー.