> それは、C++としてはゼロ除算を例外で取られられるという仕様はありませんから、
> 本来は「そうなることを条件等で事前に避ける」べきであって、
> VCの実装でWindowsの構造化例外(SEH)を使っているために「取れてしまう」だけで
は。
例としてゼロ除算を挙げたのは、まずかったですね。
スタックオーバーフローだといかがでしょう。
あと、SEHがcatch(...)で取れるのは、少なくともVC7.1の仕様のようです。
vs2003付属のmsdnのC++ Language Referenceの
Exception Handling\C++ Exception Handling\The try, catch, and throw Statements
には
If the exception-declaration statement is an ellipsis (...),
the catch clause handles any type of exception,
including C exceptions and system- or application-generated exceptions such as
memory protection, divide by zero, and floating-point violations.
との記述があります。VC固有の機能という制限は見当たりませんでした。
ん~,答えはでているんですけど
> catch(この世の全ての例外* e)
って言ったのは, 絶対起こりえないような環境に人為的にした場合
throw()をつけてもいいかどうかという質問への例えで,
本当は例外が起きているのに throw()をつけてしまうとですね
tetrapodさんが仰ったように,例外に気づくことができなくなるけど,
そんな状態でもthrow()をつけてしまってもいい物かどうかということです
いわゆる値型のメンバ変数(言葉あってるかな?)を返すだけで,
例外は起きないと思いますっていうときだけ,throw()がついていれば
わかりいいとは思いますけどね
それでもまだnewもされていない,ポインタの値も不定値のままの状態なのに
メソッドを呼び出すとか値型でも気まずいですよね?
となるとstaticの値型の静的メンバ変数とか定数を返すとかのメソッドにしか
throw()はつけられなくなってきますよね
で,throw()はそこまで厳密なのかどうかって言うことが知りたかったんです,はい
0除算などはそのクラス独自なものじゃなくて,言語の根本ぶぶんかなって,
そこはBanさんが仰った「そうなることを条件等で事前に避ける」で正解かと思います
スタックオーバーフローなどは恐らくクラスの設計に問題があるか,
そのクラスの使用者側の問題になるかなと。。。
そして,その辺りはデバグの時点でクリアになっていないと商品としてはマズイのでねぇ
たとえばそのクラスはDLLやActiveXで作られていて,operator[]とかで内部クラスを返す
メソッドを持っていると仮定してみます
で,そのDLLやActiveXが内部で持っている要素以上のインデックスをそのユーザが指定し
てしまっても,必ずNULLを返しておくようにして,例外を起こさないとthrow()をうたって
おくと,そのユーザはどうかと思うけどインデックスをメクラで総当りしても,大丈夫で
すよって,いう事になってちょっと親切なのかなと気になってました
まぁ,結構つけなくてもいいんじゃないかという意見が多かったので,つけない方向で行
きまぁす
長々と偉そうにゴメンナサイ。。。
うーーん、
僕は、グループでソフトを作るっていうことはしないので、仲澤さんと同意見ですね。
ただ、グループで作成となると、今までtetrapodさんの意見を読んでみると
いい機能だと思います。
自分が作成したクラスが他の人によって使われるとしたら、
その中でディスク・ネットワーク・パイプ等の入出力でそのクラスの禁止事項を
C++の例外としてユーザ設定する。
というのは意味があると思います。
ただ、仲澤さんとtetrapodさんが述べているマイクロソフト固有の「無視する」という
のは問題ですね。
VC2005でC/C++基準に近くなり、VC2010ではほぼ同じと思っているのですが
駄目ですか?
となると、そういったクラス同士のインターフェースの保護(でOKですか?)は、
protected等のアクセス指定子で指定するのが基本になるのですかね?
> って言ったのは, 絶対起こりえないような環境に人為的にした場合
> throw()をつけてもいいかどうかという質問への例えで,
工場で稼動する制御ソフトを作ったことがあります。
そういったソフトは、
「いかなる状況でも止まってはならない。」
又は
「いかなる状況でも非常時は必ず停止する。
また、どんな時もファンクションキー等が
押されたときに動作を再開する。」
でしたね。
まー、出来ないものは出来ないですね。
一番難しかったのが、
稼働中に人為的にRS-232Cケーブルが抜差しされても
何もなかったように動作する。
ですね。
一定間隔でシーケンサーと通信してたので難しかったです。
言語仕様(ISO/IEC14882)には規定がない以上、MSDN
> 稼働中に人為的にRS-232Cケーブルが抜差しされても
> 何もなかったように動作する。
人為的に...
断線や通信の衝突,バッファオーバーラン等のエラーではなく
明らかに通信中真っ只中を狙っての抜き差しや,高速抜き差しとかも対応しなきゃって
事?
これは無理でしょ?
何かが起きた場合,「必ず人間に通知し,安全に終了させる」ならともかく,何もなかった
ように動作するって,ひどい要求ですね
>「いかなる状況でも止まってはならない。」
これはありがちですね
でも,馬鹿みたいな要求ですよね
そういう場合は
シーケンサやローガーを背負わせて,PCは負担をなるべく感じない状態でのデータ収集の
みに徹しますねぇ
インターフェイス的にはまるでPCから制御してます風を装って。。。
> 一定間隔でシーケンサーと通信
これは通信コストが馬鹿にならない時はIOやA/Dによるハンドシェイクにしちゃいますね
でもそこまでカスタムすると,ラダーも書かなきゃいけなくなるので,ベラボーな金額に
設定するか,断っちゃいますwww
で,それを制御させるDLLの依頼で別の人がメイン部分を書くとなると throw() とかどう
なんでしょうねって事に,
DLLもクラスにしなきゃ関係ないんですけどねぇ
throw()=絶対に例外はありませんだとすると,ヘタに書かないほうがよい感じですね
この辺で何かあったら,モメそうな予感もしますし。。。
言語仕様(ISO/IEC14882)には規定がない以上、MSDNの規定はVCの仕様かと。
any exceptionがキャッチできるとはありますが
スタックオーバフローに関するexceptionを投げる規定はないです。
overflow_errorの流用なりその他なりを投げる事を仕様は要求しないですし
参照できなければ言語的には未定義動作です。
で、特定の処理系(VC)が特定の環境(Win)固有の機能(SEH)を実装に使っていて
その副次効果で未定義動作がどう振る舞うかは自由ですし
文書化する事も可能ですが、可搬性は期待できないかと。
書きかけおくってました…orz
例外仕様の本旨から外れてますね、すみません。
> これは無理でしょ?
> 何かが起きた場合,「必ず人間に通知し,安全に終了させる」ならともかく,
> 何もなかった
> ように動作するって,ひどい要求ですね
うーん、
生産ラインのソフトとしては普通みたいです。
> 何かが起きた場合,「必ず人間に通知し,安全に終了させる」ならともかく,
現場で作業する人がほとんど外国人なのでPCを操作できないのが本音みたいです。
> シーケンサやローガーを背負わせて,PCは負担をなるべく感じない状態での
> データ収集のみに徹しますねぇ
> インターフェイス的にはまるでPCから制御してます風を装って。。。
シーケンサーは、制御・タッチパネル等を行い、PCはデータ通信・データ処理を行う。
のようです。
> これは通信コストが馬鹿にならない時はIOやA/Dによるハンドシェイクにしちゃい
> ますね
溶接等のスパークのノイズが問題で、RS-232C RS-422等を使うのが基本みたいです。
> でもそこまでカスタムすると,ラダーも書かなきゃいけなくなるので,
> ベラボーな金額に設定するか,断っちゃいますwww
PC側は動作すべきであって、フローの提出はないです。
ただ、相手がシーケンサーなので打ち合わせ用の手書きのフローは必要ですね。
まぁー、通信フローしかなくシーケンサー主導なのでほとんど見せるときないです。
> 言語仕様(ISO/IEC14882)には規定がない以上、MSDNの規定はVCの仕様かと。
なるほど、統一してほしいですが難しそうですすね。
ユーザー定義に関する規定があればいいんですよね。
私も生産ラインを扱ったことありますが
「現場のおっさんは、
マウス操作すら嫌がる、パソコンなんてわからない人たちなんだから、
できるだけソフトでなんとかしてくれ」
とよく言われました
> > 稼働中に人為的にRS-232Cケーブルが抜差しされても
> > 何もなかったように動作する。
> 人為的に...
> 断線や通信の衝突,バッファオーバーラン等のエラーではなく
> 明らかに通信中真っ只中を狙っての抜き差しや,高速抜き差しとかも対応しなきゃって
> 事?
> これは無理でしょ?
> 何かが起きた場合,「必ず人間に通知し,安全に終了させる」ならともかく,何もなかっ
た
> ように動作するって,ひどい要求ですね
多分、抜き(障害発生)差し(復旧)なので、「障害がなくなったら自動復旧してくれ
よ」、という意図だと思います。
別にひどい要求ではなく、普通の要求ですね(生産現場では)。
一番大変なのが、
> 「いかなる状況でも止まってはならない。」
これがプログラム変更に関しても適用されること。まあシーケンサ側の話ですが。
現場の人たちは制御プログラムをその制御対象が動作している最中に変更しろっ
て言うんです。それも制御を止めず、運転途中の制御データと引継ぎながら。
私にはインタプリタ方式しか思い浮かばないんですけど。
> 「現場のおっさんは、
> マウス操作すら嫌がる、パソコンなんてわからない人たちなんだから、
> できるだけソフトでなんとかしてくれ」
現場では軍手などを着用しているんでPCの操作なんかできない、ってのもよく聞きま
す。
Banさん、ありがとうございます。了解です。
hiroccoさん、横槍失礼しました。
> なるほど、統一してほしいですが難しそうですすね。
そうですね。例えばスタックオーバフローの検出とか例外処理を
すべての処理系に求めてしまうと、例えばCPUやOSの支援のないプアな
組み込み環境などではオーバヘッドのせいで「使えない言語」に
成り果てるでしょうし。
> ユーザー定義に関する規定があればいいんですよね。
例外の投入自体は自分で投げる限りユーザの好きな型が投げられますし、
unexpectedやterminatedのハンドラも一応定義できますが、
処理系の内部で投げてくれ、というのはユーザ定義にはならないと思います。
言語仕様にはコンパイルオプションとかいう概念ありませんし、
もし常に例外をチェックするオーバヘッドがかかるなら、それはC++の
ゼロオーバヘッドルール(使わない機能でコストを発生させない)にも反しますし。
# ちなみにVC2005やg++で試した所やはりスタックオーバフローはcatch(...)で取れず。
スタックオーバーフローとぬるぽをVS2003で試したところ、
DebugとReleaseで動作が異なり、
Releaseだとcatch(...)に引っ懸かりませんでした。
あと、
スタックオーバーフローの場合は、
単にEXCEPTION_STACK_OVERFLOWが来ると思ったのですが、
コンパイラはcalleeの先頭でスタックサイズを調べるコードをつけていました。
# 私は、このスレッドではDebugモードだけ試して書き込んでいました。
# 例外仕様throw()からの例外送出もReleaseモードだと動作が違うようです。