質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2685閲覧

RAIIによる開放処理(デストラクタ)内での例外についてアイデア募集

Chironian

総合スコア23272

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

2クリップ

投稿2015/10/28 03:51

例外によるスタックの巻き戻し処理中に再度例外を投げるとabort()し、元の例外メッセージが失われてしまい困っています。RAIIが強力なのでよく使うのですが、デストラクタ内で検出したバグを通知する時に例外を使えないので、手間がかかるのです。
デストラクタ内での対策で済めば多少面倒でも良いのですが、あちこちに対処を書かないといけないので困ってます。あちこちに開放処理を書かないで済むことがRAIIの最大のメリットなので。

例外によるスタック巻き戻し中は元の例外を表示し、そうでない時はデストラクタ内で発生した例外を表示できれば済むのですが、何か良いアイデアは無いでしょうか?

Effctive C++を見るとこのような時はabort()するか例外を飲み込むの2つしか対策がないと書いてあります。abort()すると元の例外が失われます。飲み込むと通常時に例外が発生したことを確認するためログを見る必要があります。

ということは、これはかなり無茶な発想かもしれません。
ですので、「そんな方法はないので素直にログを確認するしかない」でも良いです。他に解がないことが確認できれば前に進めますので。

そして、実はコロンブスの卵的な解決策をちょっとだけ期待してます。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

C++では「デストラクタから外に例外送出してはならない(never throw an exception from a destructor)」というのが大原則になっています。これを裏返すと「デストラクタでは例外送出の可能性がある処理は行わないこと」と言っています。

より正確には「他の例外送出によってスタック巻き戻し(stack unwinding)処理中に呼ばれるデストラクタ中で、さらに新しい例外送出を行ってはならない」となります。これを避けるには「デストラクタ中で他の例外処理かを判定すれば良い」のですが、残念ながらC++14言語仕様と標準ライブラリの範囲内では完全な解決策がありません。Herb Sutter氏の記事 GotW#47 Uncaught Exceptions で細かい解説がなされています。

上記記事ではC++標準ライブラリ提供の std::uncaught_exception が使いづらい旨が言及されていますが、これを受けて、次世代のC++標準規格(C++17予定)では std::uncaught_exceptions への置き換えが予定されています。(末尾sのない旧来uncaught_exceptionは非推奨となる予定)

投稿2015/10/28 15:31

編集2015/10/28 15:59
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chironian

2015/10/28 17:49 編集

おお、std::uncaught_exceptionが昔からあったのですね!! 見つけることができていませんでした。(やっば英語がバリっとできないとダメですね。orz) そして、 ①std::uncaught_exceptionには問題があって、デストラクタ内でtry-catchした際のtryブロック内でstd::uncaught_exceptionを使いたい場合、適切に分岐する術がない。 ②その対策として、C++17にてstd::uncaught_exceptionsが検討されている。 つまり、デストラクタ内のtryブロックの中でstd::uncaught_exceptionを使わなければ大丈夫そうですね。 もともとstd::uncaught_exceptionを使うのはcatchブロックの中を想定していますので、上記問題に注意しておけば問題なく使えそうです。 Herb Sutter氏の言うとおり、エラー通知方法が2種類あると2つ目のエラーを見落としそうで確かに嵌りそうです。この点は複数のエラーを表示できれば解決しますので対策はできると思います。 ありがとうございました。本当に助かりました。 【追記】 ああ、上記のようなRAIIで行う処理全体が、例外処理中に呼ばれるとダメですね。 その対策は、std::uncaught_exceptionを断念する、上記RAII処理をデストラクタから呼ばない、C++17のstd::uncaught_exceptionsを使う、しかないかも?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問