C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: 例外か assert か


(過去ログ 136 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■80044 / inTopicNo.1)  例外か assert か
  
□投稿者/ 774RR (408回)-(2016/06/06(Mon) 13:49:57)

分類:[C/C++] 

プログラムの論理的誤りに対して皆さんは例外を使うか assert を使うか、どっちでしょうか。
論理的誤りとはこの場合「ソースコードの記述上の誤り」のこととします。
No80043 の「個数」に対して負値が渡される場合とか
※要するに対外リリース前には必ず修正されなければならない誤り

UI を通して渡されうる値についてはこの議題では扱わないことにします。
そういう値は事前にチェックして当然なので。
double value1, value2;
sscanf(user_input, "%lf", &value1);
if (value1<=0) { ... }
value2=log(value1); // 負値が渡されると EDOM だが、必ず事前チェックする


引用返信 編集キー/
■80045 / inTopicNo.2)  Re[1]: 例外か assert か
□投稿者/ とっちゃん (372回)-(2016/06/06(Mon) 16:02:08)
No80044 (774RR さん) に返信
> プログラムの論理的誤りに対して皆さんは例外を使うか assert を使うか、どっちでしょうか。
> 論理的誤りとはこの場合「ソースコードの記述上の誤り」のこととします。
> No80043 の「個数」に対して負値が渡される場合とか
> ※要するに対外リリース前には必ず修正されなければならない誤り
>
> UI を通して渡されうる値についてはこの議題では扱わないことにします。
> そういう値は事前にチェックして当然なので。
> double value1, value2;
> sscanf(user_input, "%lf", &value1);
> if (value1<=0) { ... }
> value2=log(value1); // 負値が渡されると EDOM だが、必ず事前チェックする
>
>

うあー。。。。課題がシビアw
例外というよりは、エラーリターンですよね?

asset は、引数は基本的にチェックします。

上記の例のような外部入力の場合は

sscanf(...);
if (value1<=0) { ... }
assert(value1>0); // プログラム的処理を行ったのでここには計算可能な値しか来ないはずという前提
value2=log(value1);

という感じですね。
何らかの理由でエラー処理をすり抜けてきたなどでも、ダメなものはダメ!という格好。


で、エラー処理をどうするかですが、受けとった値をそのまま使ってしまうと後続の処理に問題が出るなら
エラー処理は行う。
そうじゃないなら、アサーションはしても特にエラー処理は入れない。
です。

エラー処理のコストもあるし、どうせチェックしてるわけでしょー?なのでw
もちろん、クラッシュするかどうかはあえてエラーデータを流して(ユニットテスト的な処理)
クラッシュしないことくらいは検証してたりしますけどw

引用返信 編集キー/
■80058 / inTopicNo.3)  Re[1]: 例外か assert か
□投稿者/ shu (880回)-(2016/06/08(Wed) 11:48:26)
No80044 (774RR さん) に返信

仕様上、予測出来るものはassertで
予測出来ないものは例外ではないでしょうか?
引用返信 編集キー/
■80085 / inTopicNo.4)  Re[2]: 例外か assert か
□投稿者/ 774RR (409回)-(2016/06/09(Thu) 08:52:04)
> 予測出来るものはassertで
なるほど、正誤ないしは成否が事前に予測できる範囲では assert っすね。

> エラー処理をすり抜けてきたなどでも、ダメなものはダメ!
まあこの例では事前の判定をすり抜けることは想定してないのですが、
メモリ破壊などあったら「正しいはずなのに assert 」となるわけで、そういうのの検出に使えそうですね。

C++/C# 界隈ではやはり 「例外」 は 「致命傷」 扱いでしょうか。
# オイラは java とは無縁なので検査例外は考慮外。

コンストラクタで失敗するときは例外しかないのがなんだかちょっぴりいやらしい感じ
まあ仕方ないといえば仕方ないのですが。
https://msdn.microsoft.com/ja-jp/library/tyhc0kft.aspx

閑話休題

祭りってるのでリンクなど
https://social.msdn.microsoft.com/Forums/ja-JP/9155ea18-40ae-4064-8f33-0bc7f60e0b48?forum=vbgeneralja
元質問者は皆様のアドバイス「 Exception をキャッチするな」を正しく認識しているのでしょうか?
元質問者は Exception という用語を「例外」と勝手に翻訳して
「一般的にいかなる例外をもキャッチするな」と読み取っているような気のせいがします。

回答者的には Exception は当然 System.Exception (.NET の例外の基底クラス) のつもりでしょう。

System.Exception をキャッチするな
System.IO.FileNotFoundException ならキャッチしても良い
とか明示している人が居ないような・・・

引用返信 編集キー/
■80087 / inTopicNo.5)  Re[3]: 例外か assert か
□投稿者/ とっちゃん (373回)-(2016/06/09(Thu) 18:00:07)
No80085 (774RR さん) に返信
>>エラー処理をすり抜けてきたなどでも、ダメなものはダメ!
> まあこの例では事前の判定をすり抜けることは想定してないのですが、
> メモリ破壊などあったら「正しいはずなのに assert 」となるわけで、そういうのの検出に使えそうですね。
>
メモリ破壊とかの想定外な正しいはずなのに!もありますが
どちらかというと、ユーザーコードの実装ミスを可能な限り検出するが大きいです。

自分も含めて実装直後の一発目の実行は必ずバグがあると前提してるほうが安全だし
条件すり抜けはレアケースだろうから、見つけにくいので検問は随所に設けるほうが
安全という考え方ですね。

あと、何らかの修正があってもミスは発見しやすいほうがいいですからw

たぶんこの書き方は自分が今までになめてきた辛酸の数がそうさせてるだけだと思います。
なので、本当なら、logの中にチェックコードは埋めたい。
それなら外側で何をやらかしても最後の検問で全部ひっかけられるのでw



> C++/C# 界隈ではやはり 「例外」 は 「致命傷」 扱いでしょうか。
> # オイラは java とは無縁なので検査例外は考慮外。
>
javaは赤とか緑のあれだと思ってるおいらにも検査例外は無縁ですのでよくわからんですw

自分のコードでエラーリターンとするか例外を発行するか?では
C++では原則エラーリターン、C#は原則例外発行ですね

C++は、例外処理の実行コストが結構高いので、パフォーマンスに影響が出やすいのもあって
あまり例外は使わないです。昔は結構エラーは例外というのが多かったんですけどね。
上っ面は例外使うんですけど、奥のほうに行くと例外はほとんど使わなくなりますねw


これに対して、C#は例外発生時の実行コストがC++よりもずっと低いので
エラーは例外というコードが多いですし、奥のほうでも結構例外処理が入ってたりします。



> コンストラクタで失敗するときは例外しかないのがなんだかちょっぴりいやらしい感じ
> まあ仕方ないといえば仕方ないのですが。
> https://msdn.microsoft.com/ja-jp/library/tyhc0kft.aspx
>
このあたりは、あきらめてお呪いとして割り切ってますね。C#に限らず。
ここ例外かよーと思いながら使ってますw


> 閑話休題
>
> 祭りってるのでリンクなど
> https://social.msdn.microsoft.com/Forums/ja-JP/9155ea18-40ae-4064-8f33-0bc7f60e0b48?forum=vbgeneralja
> 元質問者は皆様のアドバイス「 Exception をキャッチするな」を正しく認識しているのでしょうか?
> 元質問者は Exception という用語を「例外」と勝手に翻訳して
> 「一般的にいかなる例外をもキャッチするな」と読み取っているような気のせいがします。
>
> 回答者的には Exception は当然 System.Exception (.NET の例外の基底クラス) のつもりでしょう。
>
> System.Exception をキャッチするな
> System.IO.FileNotFoundException ならキャッチしても良い
> とか明示している人が居ないような・・・
>
なんか不毛な盛り上がり方してますねえ。。。
元ネタについては、Jittaさんの一言が、一番しっくりくる気が。。。

個人的には、メッセージを出さない場面なら
try{...}catch(System.Exception){}
とかやりますね。

握りつぶしてるとか言われますけど、意図的に受け取ってるという点では
それが問題になる(出さないことで後でガタガタになる)とすれば、メモリ足りませんなエラーくらいですし
そこまで行きつく前に、バグ直せよ!>実装者 なので何の問題もないw

あとは、特定の一つをつぶせばいいの?とかかなぁ。。。
FileStream のコンストラクタなんて9種類も例外出してきますからね。
必要な例外は全部個別対処もありですが、たぶんそうはならないだろうなぁ。。。
と思います。
このあたりは実装コスト(単なるコーディングの手間)を重視かなぁw

#合間に書いてたら夕方になっちゃったw

引用返信 編集キー/
■80088 / inTopicNo.6)  Re[4]: 例外か assert か
□投稿者/ Azulean (651回)-(2016/06/09(Thu) 23:04:30)
2016/06/09(Thu) 23:06:26 編集(投稿者)
No80044 (774RR さん) に返信
> プログラムの論理的誤りに対して皆さんは例外を使うか assert を使うか、どっちでしょうか。

assert は DEBUG のみとかになっているケースも多いので、当該ビルドでデバッグしていれば誤りを検出できるなら assert の方が楽ですね。
モジュール・ライブラリとしてリリースビルドで提供して、結合した状態での確認が主となるなら、戻り値・例外としておいた方が、不具合の検出確率は上がるとも思っています。
(assert を組織内のテストに向けたリリースビルドで動くようにするというのもありかもしれませんが)

カバレッジを意識するような開発プロセスだと、throw をばらまいていると大変なことになるので、assert になりやすいかなぁ。
(非公開関数の throw の分岐まで通せと言われると地獄を見そう)


■No80087 (とっちゃん さん) に返信
> 元ネタについては、Jittaさんの一言が、一番しっくりくる気が。。。

「その行でブレークした状態で止めたい」だと捉えているので、catch ブロックに到達した時点で StackTrace で行番号を特定するだけでは不満の可能性もあるかな?と。
(最初の質問で括弧書き内とはいえ、「ソースコードの行が黄色くなる状態」と示していることが根拠)

そう思いながらも、変数の状態をウォッチで確認したいなどと言われだすと、現状は構造的に厳しいというのが正直な感想です。


> 個人的には、メッセージを出さない場面なら
> try{...}catch(System.Exception){} 
> とかやりますね。

局所的かつ、致命的なことが起きないと把握できている範囲ならありでしょう。
IOException と SecurityException など、継承元をまとめられないエラーハンドリングは確かに地獄ですし。

C# 6.0 の例外フィルターでまだマシに書けるようになったかもしれません。
(仕事柄、そちらにまだ移れていないので実感できていませんが…)


> FileStream のコンストラクタなんて9種類も例外出してきますからね。
> 必要な例外は全部個別対処もありですが、たぶんそうはならないだろうなぁ。。。
> と思います。

局所的に手を抜くか、
File I/O 系の catch ブロックをたくさん並べて Action (ラムダ)を実行する「例外ハンドリングユーティリティクラス」みたいなものを作るか、
C# 6.0 に移って例外フィルターを書くか

といったところですかね、確かに。

try
{
}
catch (Exception exception) when (exception is IOException || exception is SecurityException /* あといくつか書く */)
{
    // 既知の例外
}

引用返信 編集キー/
■80090 / inTopicNo.7)  Re[5]: 例外か assert か
□投稿者/ 774RR (410回)-(2016/06/10(Fri) 11:39:24)
カバレッジっすか・・・とりあえずウチでは今のところは求められていないのですが、悩ましい問題ですね。
投げられた例外がどこで捕らえられるかは、例外の性質上予期できないので難解ですし
(きっちりデバッグされていれば)絶対に発生しない catch 句の通過を求められたりしたらイヤんです。

組み込みマイコン上の C++ に関しては try/catch 使ったこと無いですねぇ・・・使いどころが無いというか。
客先でバグが出ても最終的には WDT でリセットさせるしか手が無いし。
組み込みマイコンソフトでは ROM 容量や実行速度の問題で、
ソースコード上に assert は書いてますが通常ビルドでは無効化していることがほとんどです。
挙動がおかしいとき、特定数個のファイルだけ有効化するように使っています。
(全ソースファイルの全部の assert を有効にすると ROM に入りきらなかったり・・・)

FileStream のような「失敗を例外で実装」している奴はしょうがないので try/catch してます。
この前書いたコードを探してみたら

try {
    using (FileStream f = new FileStream(fn, FileMode.Open, FileAccess.Read)) {
        sz = (UInt32) f.Read(image, 0, max_size);
    }
} catch (System.SystemException) { return 0; }
return sz;

でした。まあこんなもんでしょ。

そっか。オイラが例外機構を使わない/使いたくない理由はメインの業務がマイコンソフトだからか。
最近の言語 (Java/C# 等) でプログラム覚えた人だと違うのかなぁ。

引用返信 編集キー/
■80095 / inTopicNo.8)  Re[5]: 例外か assert か
□投稿者/ Jitta (198回)-(2016/06/11(Sat) 08:02:47)
No80088 (Azulean さん) に返信
> 「その行でブレークした状態で止めたい」だと捉えているので、catch ブロックに到達した時点で StackTrace で行番号を特定するだけでは不満の可能性もあるかな?と。
> (最初の質問で括弧書き内とはいえ、「ソースコードの行が黄色くなる状態」と示していることが根拠)
>
> そう思いながらも、変数の状態をウォッチで確認したいなどと言われだすと、現状は構造的に厳しいというのが正直な感想です。

それも思ったのですが、2番目の投稿を見ると、これなのかな、と。
それに、VB って、try 打ち込むと catch ブロックも勝手に入るので、何も考えずに catch しているんだろうな、と。
かつ、そういう場合って、リファレンス見ない&実行中も内容を確認しないのが多いから。

あと、VB って、デフォルトでは行番号でないので。←こっちかもしれない。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -