重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

自ら例外を全くthrowしないコードにおいて、発生する可能性がある例外は
こちらの
http://www.geocities.jp/ky_webid/cpp/library/027 …

std::bad_alloc
std::bad_cast
std::bad_typeid
std::bad_exception
std::ios_base::failure

[std::logic_error]
├ std::invalid_argument
├ std::length_error
├ std::out_of_range
└ std::domain_error

[std::runtime_error]
├ std::range_error
├ std::overflow_error
└ std::underflow_error

で全てですか?

std::bad_allocは目を瞑るとして(コードを書くことで対処するとして)
その他の全ての発生可能性を消せれば、try catch
を完全に意図通りに制御できると考えて良いでしょうか?

なお、現在
std::bad_allocは良いとして

これらのうち
std::bad_typeid
std::ios_base::failure
std::invalid_argument
std::range_error
std::overflow_error
std::underflow_error

については、自ら明示的に投げずに実際に発生する状況を確認できていません。
発生させられるコードをご存じでしたらご教授ください。

その他については以下のコードで発生したり、または状況確認がとれました。
また、この解釈で正しいでしょうか?

/////////   std::bad_cast   //////////

#include <typeinfo>

class Base { public: virtual ~Base(){} };

class Sub : public Base{ };

Base b;
Sub& s = dynamic_cast<Sub&>( b );

//Sub* s = dynamic_cast<Sub*>( &b ); ならsがNULLになるだけで例外は飛ばない。


対処法:
継承関係を完全に把握出来れば発生確率0にできるはず。
そもそもポリモーフィズムにしない状況で、しかも参照としてダウンキャストするというケースはあまりないほうがいいのではないかな?




/////////   std::bad_exception   //////////

警告C4290(http://msdn.microsoft.com/ja-jp/library/sa28fef8 …
が出るので発生自体は確認できませんでした。

対処法:
仮に対応したとしても書かなければこれ自体は起こり得ないのでは…?



/////////   std::out_of_range   //////////

#include <stdexcept>
#include <vector>

std::vector<int> i(1);
i.at(1);

対処法:
普通に配列使うときと同じように
プログラマが注意払ってれば大丈夫のはず。


/////////   std::length_error   //////////

#include <vector>

std::vector<int> i(-1);

対処法:
やはり注意深ければ起こらないのではないかと。


/////////   std::domain_error   //////////

対処法:
リンク先の解説より、書かなければ発生しないはず。(?)

A 回答 (3件)

> マジですか!?


> 具体的なところを教えてください。

VC++のmallocは、_set_new_modeと_set_new_handlerを使って、メモリの割付けに失敗した場合にユーザー定義のハンドラを呼び出すことができます。つまり、そこから例外を送出できてしまうわけです。

> そういうことを話し合いたいわけではないので

それは想像が付いていますが...

> 「ほぼ完全」で問題ありません。

「ほぼ」というのがどのレベルの話なのかがわかりません。

結局、議論しているのが、モジュールやクラスレベルの話なのか、(DLLを含めた)ライブラリレベルの話なのか、アプリケーションレベルの話なのか、それともOSや周辺機器などをすべて含めたシステム全体の話なのかによります。
    • good
    • 0
この回答へのお礼

>_set_new_modeと_set_new_handler
ありがとうございます。じっくり調べておきます。

>結局、議論しているのが、モジュールやクラスレベルの話なのか、(DLLを含めた)ライブラリレベルの話なのか、アプリケーションレベルの話なのか、それともOSや周辺機器などをすべて含めたシステム全体の話なのかによります。


そこまで詳しく状況別で解説できるほどよく御存じなのですか?
というか、「例外」という側面において

モジュールやクラスレベルの話
ライブラリレベルの話
アプリケーションレベルの話
OSや周辺機器などをすべて含めたシステム全体の話

を明確に区切ること自体は可能なのでしょうか?

OSや周辺機器がなければ実行できませんし、出来るものはアプリケーションなわけですし、ライブラリを使えば便利だと思いますし、時には自分で作るかもしれません。そしてC++なら当然モジュール・クラスはかかわらざるを得ないと思います。

加えて、分からないので質問しているために、どのレベルの話に該当し得るのかが分かりません。
当の私は、そんなに大きな話に膨らむとは全く想定していませんでしたので

この際、不明瞭ならば

>std::bad_allocは目を瞑るとして(コードを書くことで対処するとして)
その他の全ての発生可能性を消せれば、try catch
を完全に意図通りに制御できると考えて良いでしょうか?


この部分は全くなしとして読んでください。
この質問での最大の目的は

std::~

の上記12種類の再現コードと、再現コードはなくてもせめておおよそ十分といえるであろう対処法を確保したいというところにあります。

お礼日時:2010/03/17 02:31

> そこまで詳しく状況別で解説できるほどよく御存じなのですか?



そんな難しい話ではありません。
例えば、クラスやライブラリなど、それ単独では動かないような場合、どんな使い方をされるかはクライアントコードしだいになります。
その場合、各種ハンドラや別のスレッドなど、自分ではコントロールし切れない要素が出てしまうわけです。
アプリケーションであれば多少ましですが、それでも、別のプロセスによって動作を変えられる可能性も完全には否定できません。
OSの状態や周辺機器の状態までコントロールでき、ネットワークにも接続しないのであれば、完全に制御できる可能性はずっと高まります。
要はそういうことです。

> その他の全ての発生可能性を消せれば、try catch
> を完全に意図通りに制御できると考えて良いでしょうか?

本当に「すべての発生可能性を消せれば」その通りです。

この回答への補足

約二年越しでの補足となりますが
これらの再現コードはいまだ分かりません。

とはいえ
とりあえず今のところ
自分自身で作ってきた
アプリケーションに於いて
std::~
系統の例外に「手を焼いた」ケースは
std::bad_alloc含め一度もないという結果になっています。

また5件に達したら締め切らないと新規質問を出来ないという教えてgooのルールもあるので
この件は「まぁそれほど心配もいらないだろう」と考え

解決とさせていただきます。

補足日時:2012/02/14 21:35
    • good
    • 0
この回答へのお礼

そういうことであればその通りでしょうが

そういう概念自体であればわざわざ問答しなくても考えればわかるわけで、私が質問してる意味自体もjactaさんが回答している意味自体もなくなってしまいます。

どんなライブラリだって、常識的に考えておかしい使い方されたらおかしい結果になって然りと思いますが…
「プログラマがコントロール出来てるという前提として」なのでクライアントコード次第…という事は成り立ちません。

世に別のプロセスによって動作を変えられて、そのあらゆるパターンに対してうまく対処しきれるようなアプリケーションはどれほどあるでしょうか?

その必要は、積極的にほかのアプリと関わるようなアプリケーション、あるいはそういった部分以外
基本的には考える必要ないと思っていいのではないでしょうか?

私はもっと「自分で作るアプリケーション内、あるいは自分で書いた範囲内で判断すれば少なくとも綺麗に完結出来てるようなコードを書こうとすれば」という側に近い視点での話をしたいのです。実際にコードを書こうとしてるから疑問を解決したいわけで、現実的にはどう手を打つべきかを中心に考えないと、さっぱり要領を得ません。


それで、結果として

std::bad_typeid
std::ios_base::failure
std::invalid_argument
std::range_error
std::overflow_error
std::underflow_error


についてはご存じないのですか?
記述を見れば対処法のある程度の予想は出来るものもますが
再現コードの具体例が分からないと確信が出来ません。

お礼日時:2010/03/17 14:09

まずは処理系を明確にすべきです。



> 警告C4290(​http://msdn.microsoft.com/ja-jp/library/sa28fef8 …​)
> が出るので発生自体は確認できませんでした。

とのことなので、Visual Studio 2005なのでしょうか?

> その他の全ての発生可能性を消せれば、try catch
> を完全に意図通りに制御できると考えて良いでしょうか?

他人が作ったライブラリを一切使うことができないということになりますが、本当にそれが可能でしょうか?
規格上は、qsortやbsearchのようなコールバックを渡すもの以外は、標準Cライブラリの関数は例外を送出しないことになっていますが、VC++はmallocが例外を送出するかもしれないという反則をやっていますからね。
標準C++ライブラリの場合は、明示的に例外指定throw()がなければ、どんな例外が送出されるかはわかりません。処理系の独自ライブラリであれば、なおさらです。

それに、完全に制御しきれなければ、可能性を完全に消すことはできません。
例えば、Visual Studio 2005であれば、.NETのコードと混在しているのであれば、ThreadAbortExceptionが非同期に送出される可能性などは考えなくてもよいのでしょうか?
未定義の動作の結果、いわゆる構造化例外が発生した場合はどうでしょうか?
別のスレッドが、SetThreadContextを使うなどして、まったく関係のない処理を割り込ませた場合はどうですか?

どんなにレアケースであっても、完全かどうかを議論するのであれば、考慮しなけれななりません。
    • good
    • 0
この回答へのお礼

>まずは処理系を明確にすべきです。

それについてはごもっともです。
VC++2008EEを現在使っていますが、そのうち新しい方へ移っていく予定です。

>本当にそれが可能でしょうか?

それは分かりません。ただし、私が書いた

>その他の全ての発生可能性を消せれば、try catch
を完全に意図通りに制御できると考えて良いでしょうか?

は、あくまでたとえです。本意は「そういう状況がもしあったら可能かどうか」ということが知りたいのです。

人の書いたライブラリに胸を張って「副作用含め完全に例外に対応できています」といえる人はいないと思います。
仕様を隅々まで見なければ言えないと思います。

現実的には、作った人自身例外を送出することがはっきりわかってるのであれば仕様書ぐらいあってもおかしくないと思いますし、それしか見れない場合はそれを信頼するしかありません。


ただ、
>mallocが例外を送出するかもしれないという反則

マジですか!?
具体的なところを教えてください。


現在は混在していないので.NETについてはその可能性はないです。

「プログラマが全部把握してて主体」になっている、という前提では、という話なので
「別のスレッドが」勝手に行動するわけではありません
そのスレッドの動きもコントロールしてるとして、という前提では、という話です。

>完全かどうかを議論するのであれば、考慮しなけれななりません。

そういうことを話し合いたいわけではないので「ほぼ完全」で問題ありません。

構造化例外についてですが、それもコード側で現実的にコントロールできるような部分は対処し、普通のアプリケーションはそこまで首を突っ込むべきじゃないだろうとか、コード側では普通どうにもならないかと…という部分は無視することにします。

といっても厳密な「普通」の線引はこの宇宙の構造的に無理だと思うので、ある程度察していただけるとありがたいです。

お礼日時:2010/03/17 01:51

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!