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

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

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

Re[3]: finallyのテスト方法がわからない


(過去ログ 101 を表示中)

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

■60006 / inTopicNo.1)  finallyのテスト方法がわからない
  
□投稿者/ furu (25回)-(2011/06/15(Wed) 14:28:20)

分類:[C#] 

VS2010 C#4.0

簡単そうなのにわからなくて、今まで誤魔化していたことを
今日こそ聞きます。きっと私が知らないだけだと思います。

デバック実行中に例外アシスタントが表示された後に
finally処理を実行させたいのですがやり方がわかりません。
「続行」すると同じ例外アシスタントが表示されるだけです。

            try
            {
                var d = new DateTime(2011, 0, 0);

                MessageBox.Show(d.ToString());
            }
            finally
            {
                MessageBox.Show("finally");
            }

実際のプログラムでは、"finally"が表示される。
例外アシスタントが表示されてから、"finally"が表示されることを
確認したい。

よろしくお願いします。

引用返信 編集キー/
■60008 / inTopicNo.2)  Re[1]: finallyのテスト方法がわからない
□投稿者/ shu (788回)-(2011/06/15(Wed) 14:34:15)
No60006 (furu さん) に返信

finallyの前にcatchしないと駄目ですよ。
throwされて放置された例外の後にfinallyが実行されるわけではありません。
引用返信 編集キー/
■60009 / inTopicNo.3)  Re[2]: finallyのテスト方法がわからない
□投稿者/ furu (27回)-(2011/06/15(Wed) 15:14:07)
No60008 (shu さん) に返信
> ■No60006 (furu さん) に返信
>
> finallyの前にcatchしないと駄目ですよ。
> throwされて放置された例外の後にfinallyが実行されるわけではありません。

でも、catchはアプリケーションがやってくれている(「アプリケーションの
コンポーネントで、ハンドルされていない…」)ので

   throw→ 各finally → catch

と思っていました。デバッグのステップ実行で
このfinallyをテストしたいのです。

catchがない(設計的に絶対に起きない思っていた)プログラムで
finallyがある(それでも保険としてやりたいことがある)場合の
テストがしたいです。

それとも、catchのない、finallyは絶対に書くべきでないのでしょうか?

引用返信 編集キー/
■60010 / inTopicNo.4)  Re[3]: finallyのテスト方法がわからない
□投稿者/ shu (789回)-(2011/06/15(Wed) 15:33:31)
No60009 (furu さん) に返信

catchしないと例外が発生した場合、finallyは実行されません。

下記を実行した場合の結果は
testFunc finally
Main Exception:Exception
Main finally
となります。

static void Main()
{
	try
	{
		testFunc();
	}
	catch (Exception ex)
	{
		Console.WriteLine("Main Exception:" + ex.Message);
	}
	finally
	{
		Console.WriteLine("Main finally");
	}
}

private static void testFunc()
{
	try
	{
		throw new Exception("Exception");
	}
	finally
	{
		Console.WriteLine("testFunc finally");
	}
}



下記の処理を実行した場合、結果は次のようになります。
finally:0
try:1
finally:1
finally:2
try:3
finally:3
finally:4
try:5
finally:5
finally:6
try:7
finally:7
finally:8
try:9
finally:9

for (int i = 0; i < 10; i++)
{
	try
	{
		if (i % 2 == 0)
		{
			continue;
		}
		Console.WriteLine("try:" + i);
	}
	finally
	{
		Console.WriteLine("finally:" + i);
	}
}



引用返信 編集キー/
■60012 / inTopicNo.5)  Re[4]: finallyのテスト方法がわからない
□投稿者/ furu (29回)-(2011/06/15(Wed) 16:01:49)
No60010 (shu さん) に返信

例を作って頂き、ありがとうございます。
変更し、テストしました。

下記を実行した場合の結果は
ハンドルされていない例外: System.Exception: Exception
   場所 ConsoleApplication1.Program.testFunc()
   場所 ConsoleApplication1.Program.Main(String[] args)
testFunc finally
Main finally
となります。

catchしなくても例外が発生した場合、finallyは実行されているようです。
この時のfinallyをテストしたいのですが無理でしょうか?
また、shuさんのいう実行されないというのは、どういう意味ですか?

static void Main()
{
	try
 	{
 		testFunc();
 	}
 	finally
 	{
 		Console.WriteLine("Main finally");
 	}
}

private static void testFunc()
{
	try
	{
		throw new Exception("Exception");
	}
	finally
	{
		Console.WriteLine("testFunc finally");
	}
} 
 

引用返信 編集キー/
■60013 / inTopicNo.6)  Re[5]: finallyのテスト方法がわからない
□投稿者/ ビート (1回)-(2011/06/15(Wed) 16:13:08)
> catchしなくても例外が発生した場合、finallyは実行されているようです。
> この時のfinallyをテストしたいのですが無理でしょうか?

catchしなくても例外が発生した場合、finallyが実行されたなら、それでいいのでは?
finallyの何をテストしたいのですか?
どういう理由があるか説明した方がアドバイスが得やすいと思いますが、如何?
引用返信 編集キー/
■60014 / inTopicNo.7)  Re[5]: finallyのテスト方法がわからない
□投稿者/ shu (790回)-(2011/06/15(Wed) 16:16:40)
No60012 (furu さん) に返信

> 下記を実行した場合の結果は
> ハンドルされていない例外: System.Exception: Exception
> 場所 ConsoleApplication1.Program.testFunc()
> 場所 ConsoleApplication1.Program.Main(String[] args)
> testFunc finally
> Main finally
> となります。
それはデバッグ中でない実行結果と言うことですね。
デバッグは例外が解除されるまで次を実行しないのでcatchされないfinallyは
実行されないということです。(例外が出ないようにするのがデバッグなのでは?)
デバッグ中に今回のような現象が発生することがあったらcatchするか例外が発生しないよう
修正が必要ということになるのではないでしょうか?
引用返信 編集キー/
■60015 / inTopicNo.8)  Re[6]: finallyのテスト方法がわからない
□投稿者/ furu (30回)-(2011/06/15(Wed) 16:34:38)
No60013 (ビート さん) に返信

そうですね。
デバッガで簡単にfinallyに入る方法があるだろうと考え、
理由は書きませんでした。

理由は、2つあります。

1.保険の為、catchのないfinallyで書いている部分の
  例外でのスルーテストがしたい。

2.デバック中にバグで停まった場合でも
  必ずfinally(一時ファイルの削除,Excelのプロセス中止等)を実行したい。
  こちらの方が本命です。
  今は、「再起動」か「すべて中止」をして
  手作業でfinallyと同じことをやっています。

それからcatchは、本当のエラーを見逃す恐れがあるので
極力使用しないコーディングをしています。
System.IO.Directory.CreateDirectoryのように
catchでしか失敗を判別できない場合は、
catchを使用しています。

よろしくお願いします。
引用返信 編集キー/
■60016 / inTopicNo.9)  Re[7]: finallyのテスト方法がわからない
□投稿者/ shu (791回)-(2011/06/15(Wed) 16:51:51)
No60015 (furu さん) に返信

必ずcatch付けた方がいいと思いますがデバッグコンパイル時だけでも
付けるとかしてみてはどうでしょう。
引用返信 編集キー/
■60018 / inTopicNo.10)  Re[6]: finallyのテスト方法がわからない
□投稿者/ furu (31回)-(2011/06/15(Wed) 16:54:15)
No60014 (shu さん) に返信
> ■No60012 (furu さん) に返信
> 
>>下記を実行した場合の結果は
>>ハンドルされていない例外: System.Exception: Exception
>>   場所 ConsoleApplication1.Program.testFunc()
>>   場所 ConsoleApplication1.Program.Main(String[] args)
>>testFunc finally
>>Main finally
>>となります。
> それはデバッグ中でない実行結果と言うことですね。
> デバッグは例外が解除されるまで次を実行しないのでcatchされないfinallyは
> 実行されないということです。(例外が出ないようにするのがデバッグなのでは?)
> デバッグ中に今回のような現象が発生することがあったらcatchするか例外が発生しないよう
> 修正が必要ということになるのではないでしょうか?

そうです。警告も出ず、ビルドでき、通常の使用で通る可能性があるのに
VS2011ではデバッグできないということですね。
他の統合デバッガではできたのであるかなと思いました。
ちょっと皮肉って終わりにします。

	static void Main()
	{
		Application.EnableVisualStyles();
		Application.SetCompatibleTextRenderingDefault(false);
		try
		{
			Application.Run(new Form1());
		}
		finally
		{
			どんな事があっても一時データを消去();
		}
	}

	例外の時、一時データがちゃんと消えるかテストできないんだって

引用返信 編集キー/
■60019 / inTopicNo.11)  Re[8]: finallyのテスト方法がわからない
□投稿者/ furu (32回)-(2011/06/15(Wed) 17:02:19)
shuさん、ありがとうございます。

デバッグの時のみ、付けるようにしました。

	try
	{
		Application.Run(new Form1());
	}
	#if DEBUG
	catch
	{
		throw null;
	}
	#endif

■No60016 (shu さん) に返信
> ■No60015 (furu さん) に返信
> 
> 必ずcatch付けた方がいいと思いますがデバッグコンパイル時だけでも
> 付けるとかしてみてはどうでしょう。

解決済み
引用返信 編集キー/
■60030 / inTopicNo.12)  Re[7]: finallyのテスト方法がわからない
□投稿者/ Azulean (765回)-(2011/06/15(Wed) 22:46:05)
No60018 (furu さん) に返信
> static void Main()
> {
(略)
> finally
> {
> どんな事があっても一時データを消去();
> }
> }

そもそも、別スレッドで例外が出て、catch されなかった場合、この finally は実行されません。

# 極論を言うと、ユーザーによってプロセスを殺される(タスクマネージャーで強制終了)、電源をいきなり切るといった時はどんな方法でも無理です。
引用返信 編集キー/
■60031 / inTopicNo.13)  Re[9]: finallyのテスト方法がわからない
□投稿者/ Azulean (766回)-(2011/06/15(Wed) 23:44:52)
もし、メインスレッドで例外が発生したときであっても、デバッグなしで実行した時、Application.Run の中のメッセージループは基本的に try-catch で囲まれています。
この catch の中で例外が発生したときのいつもの継続 or 終了のダイアログを表示する処理が行われます。
従って、Application.Run の外側まで例外が飛んでくることはまれだと思われます。

また、終了ボタンであのダイアログを閉じた場合、Environment.Exit が呼び出され、finally が実行されることなく終了するかもしれません。
引用返信 編集キー/
■60034 / inTopicNo.14)  Re[1]: finallyのテスト方法がわからない
□投稿者/ なし (24回)-(2011/06/16(Thu) 10:10:19)
2011/06/16(Thu) 14:00:26 編集(投稿者)
2011/06/16(Thu) 10:27:46 編集(投稿者)

No60006 (furu さん) に返信
> デバック実行中に例外アシスタントが表示された後に
> finally処理を実行させたいのですがやり方がわかりません。
> 「続行」すると同じ例外アシスタントが表示されるだけです。

オプションで変更できます。

ツール → オプション → デバッグ → 全般
[例外処理アシスタントを有効にする] の下にある
[ハンドルされていない例外で呼び出し履歴をアンワインドする]
のチェックを解除してください。

デフォルトの状態(チェック有)は、エラー発生行をその場で修正してエディットコンティニュできるように、わざわざアンワインドしてくれていると言えますね。

引用返信 編集キー/
■60035 / inTopicNo.15)  Re[8]: finallyのテスト方法がわからない
□投稿者/ furu (33回)-(2011/06/16(Thu) 14:11:46)
No60030 (Azulean さん) に返信
> ■No60018 (furu さん) に返信
>> static void Main()
>> {
> (略)
>> finally
>> {
>> どんな事があっても一時データを消去();
>> }
>> }
>
> そもそも、別スレッドで例外が出て、catch されなかった場合、この finally は実行されません。
>
> # 極論を言うと、ユーザーによってプロセスを殺される(タスクマネージャーで強制終了)、電源をいきなり切るといった時はどんな方法でも無理です。

コメントありがとうございます。

問題点はfinallyを実行するかどうかでなく、
「デバッグなしで開始」での動作(throw → finally → finally → ダウン)が
「デバッグ開始」で実行(テスト)できないことです。

引用返信 編集キー/
■60037 / inTopicNo.16)  Re[10]: finallyのテスト方法がわからない
□投稿者/ furu (34回)-(2011/06/16(Thu) 14:20:18)
No60031 (Azulean さん) に返信
> もし、メインスレッドで例外が発生したときであっても、デバッグなしで実行した時、Application.Run の中のメッセージループは基本的に try-catch で囲まれています。
> この catch の中で例外が発生したときのいつもの継続 or 終了のダイアログを表示する処理が行われます。
> 従って、Application.Run の外側まで例外が飛んでくることはまれだと思われます。
>

そうですが、このtry-catchを入れる事でデバッガをだませて
当初の目的(finallyのテスト)は、果たせました。
デバッガは、Application.Run の中のメッセージループはtry-catch で囲まれていることを
知らないか知らない振りをしているようです。
引用返信 編集キー/
■60038 / inTopicNo.17)  Re[2]: finallyのテスト方法がわからない
□投稿者/ furu (35回)-(2011/06/16(Thu) 14:31:09)
No60034 (なし さん) に返信
> 2011/06/16(Thu) 14:00:26 編集(投稿者)
> 2011/06/16(Thu) 10:27:46 編集(投稿者)
>
> ■No60006 (furu さん) に返信
>>デバック実行中に例外アシスタントが表示された後に
>>finally処理を実行させたいのですがやり方がわかりません。
>>「続行」すると同じ例外アシスタントが表示されるだけです。
>
> オプションで変更できます。
>
> ツール → オプション → デバッグ → 全般
> [例外処理アシスタントを有効にする] の下にある
> [ハンドルされていない例外で呼び出し履歴をアンワインドする]
> のチェックを解除してください。
>
> デフォルトの状態(チェック有)は、エラー発生行をその場で修正してエディットコンティニュできるように、わざわざアンワインドしてくれていると言えますね。
>

ありがとうございます。
アンワインドすることは無くなりましたが、やはり「デバッグ開始」と「デバッグなしで開始」の動作は
違っていました。INT 21H, AH=4CHに行く前にデバッガが止めちゃうんだよね。

解決済み
引用返信 編集キー/
■60039 / inTopicNo.18)  Re[3]: finallyのテスト方法がわからない
□投稿者/ なし (25回)-(2011/06/16(Thu) 15:37:19)
No60038 (furu さん) に返信
> アンワインドすることは無くなりましたが、やはり「デバッグ開始」と「デバッグなしで開始」の動作は
> 違っていました。INT 21H, AH=4CHに行く前にデバッガが止めちゃうんだよね。

INT 21H のところは理解できてないのですが、
UnhandledExceptionMode の指定で同じにできるかもしれません。

static void Main()
{
  Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

※解決済み状態は一応そのままにしておきますね。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -