例外処理 例外型が不明な場合について

[戻る]
wood 2005/03/01(火) 06:12:28
OS:WinXP VC6(SP6) コンソールアプリ

以下のサンプルがありました
------------------------------------------------------------------
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{

 try
 {
 int    request;
 cout << "整数を入力してください:";
 cin  >> request;

 if(request == 1)
   throw "THIS IS ERROR";
 else
   if(request == 1)
      throw 10;
   else
      throw 1.23;  ←ここ.1
    
 }

 catch(char* e)
 {
  cout << "char*型エラー発生:" << e << endl;
 }
 catch(int e)
 {
 cout << "int型エラー発生:" << e << endl;
 }
 catch(...)   ←ここ.2
 {
 cout << "その他" << endl;
 }
return 0;
}
-------------------------------------------------------------
このサンプルの「ここ.1」の例外(Double型)は「ここ.2」でしか
判断できませんが
仮に「ここ.1」の部分が関数だった場合、関数内部で型が不明なthrowを
発生させていたとすると、どのようにしてますでしょうか?

1、サンプルのように「その他」で終わらせ、あきらめる以外ない
2、他に値を取得する方法がある
3、そんな記述は絶対しない(ありえない)

どれでしょうか
3の人は回答不要(他人の作った関数やDLLを使用しない人でしょうから)

もし 2があるのなら是非教えてください

Ban 2005/03/01(火) 11:02:42
ソースがあるなら検索なりできるとして、ここではソースもないとして。
「投入されうる例外」はその関数のインターフェイスの一部ですので、
製作者に仕様を確認するしかないのではないかと思います。
そのコンタクトも取れず保守も保証もない代物であれば、1 で我慢しかないような気がします。

2は多大な労力をかけたリバースエンジニアリング(ライセンスに問題がなければ)くらいしか方法はないと
思います。(組み込み型の double なら多少楽かも?)

# ありえないとは言いませんが、自分で書くなら 3 を守りたいです。

tetrapod 2005/03/01(火) 11:19:24
throw "THIS IS ERROR"; を catch(char* e) で取得できないことはおいといて

まったく不明な例外を投げるのであれば、可能なのは「受け取るだけ」であり、詳細を判別する
ことは不可能です。
つまり解は1

C++ 標準ライブラリは std::exception 派生型の例外を投げることで「まったく不明」な例外
を排除しています。
ということで、ライブラリを作る側と使う側で合意が取れるのなら、
解3「特定基底クラス派生の例外オブジェクトを投げる」
ようにすることが望ましく、まったく不明な例外など使わないに1票。

合意もソースも仕様書も無いなら解1しか手はないです。
# リバースエンジニアリングしてまで解2の策を取りたくはないなぁ。

REE 2005/03/01(火) 11:20:29
仕様が不明な例外を受けた場合は、その意味するところも不明でしょう。
よって、その型や値がわかっても、使い道はないでしょうから、1で充分と思います。

PATIO 2005/03/01(火) 14:52:11
思うに、catch(...)は正にいわれているような事態に対応するための手段だと思います。
補足しないとアプリが意図しないダイアログが出てしまいますから、
それを出させないで全て使う側の管理の下に表示等を行う為の最終手段ではないかと。
皆さん言われているように、何がくるのかわからない例外では使いようがないというのが
正道でしょう。基本的に仕様として規定されていない物であれば、対応する処置は出来ない
ので、取り合えず受けたとしても「想定外の例外が発生しました」とでも出すしかなさそ
うですね。

wood 2005/03/02(水) 11:21:10
[[解決]]
皆さんの大変貴重なご意見ありがとうございます

「tetrapod さん」に至っては、サンプル提示ミスのご指摘まで頂きありがとうございます

>catch(...)
は皆さんの言うとおり、1の「あきらめる」ほか、なさそうですね
C++の基礎再学習を行っていましたら、突っ込んだ解説のようなものが見当たらず
皆さんの意見を伺ってみた次第です、ありがとうございました

tetrapod 2005/03/02(水) 12:00:04
ISO/IEC 14882 には throw("string_literal") を catch(char*) で受け取れない
と明記されています(「受け取れてはならない」という処理系作者への要請の意)
15.1 Throwing Exception 3

が VC++6 や bcc-5.5.1 では受け取れてしまいます。その意味でサンプルは正しいです。
gcc-3.3.4 では受け取れなくなっています。
# 規格書より古い処理系なのでしかたがないのですが > VC++6

文字列リテラルは const char* でなら受け取れるので catch(const char*) ならOK

シャノン 2005/03/03(木) 01:30:36
「catch( ... ) はどうしようもない」と言うよりも、「どうしようもないから catch
( ... )」なのではないでしょうか。
何が言いたいかというと、catch( ... ) には、例外オブジェクトとして受け取る変数名
を書けませんよね。
こういう仕様が策定された時点で、解2は無いものとされていたのではないでしょうか。

ちなみに、VC++ 限定(バージョン依存かも。7.1 では大丈夫)の、可搬性のない方法な
ら、ひょっとしたら可能かもしれません。
0xe06d7363 でぐぐると、何か見つかるかも…

wood 2005/03/03(木) 19:45:24
「tetrapod さん」「シャノン さん」 ありがとうございます
コンパイラによっては、制限事項が違ったりしますので必ずしもVCが正しいわけでは
無いことを肝に銘じておきます

「0xe06d7363」例外構造体番号と言うものらしいですね
MSDNには「WINDOWS OS 固有のもの」という表現がありました

古いスレッドには追加発言できません。