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

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

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

Re[13]: .NetFramework3.5から4に変更すると例外発生


(過去ログ 102 を表示中)

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

■60820 / inTopicNo.1)  .NetFramework3.5から4に変更すると例外発生
  
□投稿者/ Ys (1回)-(2011/07/20(Wed) 11:57:52)

分類:[C#] 

開発環境:VisualStudio2010
使用言語:C#

初めて投稿させていただきます。
全くの初心者ではないですが、知識はすごく浅いので、ご迷惑をおかけすると思いますが、よろしくお願い致します。


もともと.NET Framework3.5で開発していたシステムの対象のフレームワークを、.NET Framework4に変更しました。
ビルドは問題なく通るのですが、システムを起動すると以下のコマンドで例外が発生するようになってしまいました。

if( Dlg.ShowDialog( this ) == DialogResult.OK )
※"Dlg"はSystem.Windows.Forms.Formを継承して作成した画面になります。

例外の発生するタイミングは以下になります。
@ShowDialogでDlg画面が表示
ADlg画面を閉じる
B『'System.StackOverflowException' のハンドルされていない例外が System.Windows.Forms.dll で発生しました。』発生

'System.StackOverflowException'は無限ループ等で発生する例外だと思うのですが、
もともと.NET Framework3.5では問題なく動いていたように、無限ループにはなっていないと思っています。

フレームワークを変更しただけで、他には特に変更していません(参照設定しているDLLでフレームワークに関連するものは変更しています)。
なにか思いつくことがある方、ご教授をお願いできないでしょうか?
よろしくお願い致します。

引用返信 編集キー/
■60821 / inTopicNo.2)  Re[1]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ shu (870回)-(2011/07/20(Wed) 12:12:18)
No60820 (Ys さん) に返信

Dlg内の処理をとりあえず全部行わないようにしてみる。1個づつ戻していくとどうでしょう?
引用返信 編集キー/
■60823 / inTopicNo.3)  Re[2]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Ys (2回)-(2011/07/20(Wed) 14:17:48)
No60821 (shu さん) に返信
> ■No60820 (Ys さん) に返信
>
> Dlg内の処理をとりあえず全部行わないようにしてみる。1個づつ戻していくとどうでしょう?

shu さん
返信ありがとうございます。

教えていただいた通り、Dlg内の処理を1つずつチェックしてみました。
そうしたところ、1つの処理(あるDLLをコール)が原因ということがわかりました。
詳しくはこれから調べてみますが、場所が特定できただけでもありがたいです。

ありがとうございました。


引用返信 編集キー/
■60836 / inTopicNo.4)  Re[3]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Ys (4回)-(2011/07/20(Wed) 18:32:08)
すいません、やはり解決できませんでした。

shu さんのおかげで、問題がDLLをコールしているところにあることはわかりました。
(このDLLは『C++Builder』で作成したDLLで、「DllImport」で利用しています)

ただ、このコールで無限ループに陥っているわけでもなく
落ちているわけでもなく
予期せぬ値を戻しているわけでもありません。
正常な結果を戻しています。
もちろん、.NET Framework3.5では問題ありませんでした。

なにか思いつくことがある方、ご教授をお願いできないでしょうか?
よろしくお願い致します。

引用返信 編集キー/
■60866 / inTopicNo.5)  Re[4]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ ヴァン (84回)-(2011/07/21(Thu) 18:48:59)
No60836 (Ys さん) に返信
> なにか思いつくことがある方、ご教授をお願いできないでしょうか?
> よろしくお願い致します。

的外れかもしれませんが、64ビットアプリとか32ビットアプリとかは関係ありませんか?
引用返信 編集キー/
■60871 / inTopicNo.6)  Re[4]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Azulean (792回)-(2011/07/21(Thu) 22:57:26)
No60836 (Ys さん) に返信
> ただ、このコールで無限ループに陥っているわけでもなく
> 落ちているわけでもなく
> 予期せぬ値を戻しているわけでもありません。
> 正常な結果を戻しています。

関数をコールすることで、何か仕込んでいるのでしょうか。
たとえば、呼び出したウィンドウのハンドルを登録しておいて、そのウィンドウがなくなるときに後処理をしていて、その処理が無限ループするとか。


> なにか思いつくことがある方、ご教授をお願いできないでしょうか?

正直なところ、その DLL 特有の問題だと考えられるので、どういった性質のものか、どういった処理をしているのか踏み込んでいただけないと、推測は困難だと思われます。



No60866 (ヴァン さん) に返信
> 的外れかもしれませんが、64ビットアプリとか32ビットアプリとかは関係ありませんか?

揚げ足で申し訳ないですが、64 ビットアプリケーションで 32 ビット DLL を読み込むことはできません。(逆も同様)
この場合、関数を呼び出した時点で例外が発生するので、後から障害が出るという動き方をしないと予想されます。
参考までに。
引用返信 編集キー/
■60873 / inTopicNo.7)  Re[5]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ ロートルプログラマ (1回)-(2011/07/21(Thu) 23:24:59)
>このDLLは『C++Builder』で作成したDLL
Builderのバージョンが不明ですが、Vclを使っているものだとデータセグメントとスタックセグメントを
疑ってみてください。32ビットでなんでセグメント?と思うでしょうが、少なくともVclを使ったBuilder
のアプリではスタック上のローカル変数へのポインタをDirectShowのようなスレッド前提のAPIに渡した
場合には正しく動作しません(というか、しない場合が多い)。言っている意味がわからない場合は無視し
ていただいてかまいません。

引用返信 編集キー/
■60878 / inTopicNo.8)  Re[5]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Ys (5回)-(2011/07/22(Fri) 11:35:48)
2011/07/22(Fri) 11:54:43 編集(投稿者)
2011/07/22(Fri) 11:54:32 編集(投稿者)

追加位置変更しました。
引用返信 編集キー/
■60879 / inTopicNo.9)  Re[6]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Ys (6回)-(2011/07/22(Fri) 11:55:37)
返信が遅くなって申し訳ありません。

No60866 (ヴァン さん) に返信

ヴァン さん
返信ありがとうございます。

> 的外れかもしれませんが、64ビットアプリとか32ビットアプリとかは関係ありませんか?

どちらも32ビットで開発しておりますので、大丈夫だと思います。


No60871 (Azulean さん) に返信

Azulean さん
返信ありがとうございます。

>>ただ、このコールで無限ループに陥っているわけでもなく
>>落ちているわけでもなく
>>予期せぬ値を戻しているわけでもありません。
>>正常な結果を戻しています。
>
> 関数をコールすることで、何か仕込んでいるのでしょうか。
> たとえば、呼び出したウィンドウのハンドルを登録しておいて、そのウィンドウがなくなるときに後処理をしていて、その処理が無限ループするとか。
> 正直なところ、その DLL 特有の問題だと考えられるので、どういった性質のものか、どういった処理をしているのか踏み込んでいただけないと、推測は困難だと思われます。

説明不足で申し訳ありませんでした。
DLLでは、フォルダパスとXMLファイルパスを受け取り、そのXMLファイルにフォルダパスの内容(あるファイル情報)を出力する処理を行っています。
DLLはこれだけの処理です。
この処理終了後、DLLは使用していません。
(これだけの処理ならDLLにしなくても・・・と言われる方がいるかもしれませんが、それはとりあえず置いといてください(-人-;))


>>的外れかもしれませんが、64ビットアプリとか32ビットアプリとかは関係ありませんか?
>
> 揚げ足で申し訳ないですが、64 ビットアプリケーションで 32 ビット DLL を読み込むことはできません。(逆も同様)
> この場合、関数を呼び出した時点で例外が発生するので、後から障害が出るという動き方をしないと予想されます。
> 参考までに。

そうなんですね。
安心しました。
ありがとうございます。


No60873 (ロートルプログラマ さん) に返信

ロートルプログラマ さん
返信ありがとうございます。

> >このDLLは『C++Builder』で作成したDLL
> Builderのバージョンが不明ですが、Vclを使っているものだとデータセグメントとスタックセグメントを
> 疑ってみてください。32ビットでなんでセグメント?と思うでしょうが、少なくともVclを使ったBuilder
> のアプリではスタック上のローカル変数へのポインタをDirectShowのようなスレッド前提のAPIに渡した
> 場合には正しく動作しません(というか、しない場合が多い)。言っている意味がわからない場合は無視し
> ていただいてかまいません。

すいません、知識不足で。。。
ちなみにBuilderのバージョンは5です。

引用返信 編集キー/
■60880 / inTopicNo.10)  Re[1]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ todo (158回)-(2011/07/22(Fri) 13:35:13)
No60820 (Ys さん) に返信
> 'System.StackOverflowException'は無限ループ等で発生する例外だと思うのですが、
> もともと.NET Framework3.5では問題なく動いていたように、無限ループにはなっていないと思っています。

無限再帰呼び出しとか。
デバックで例外が発生したときに「呼び出し履歴」を見れば分かります。
引用返信 編集キー/
■60881 / inTopicNo.11)  Re[7]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ ロートルプログラマ (2回)-(2011/07/22(Fri) 13:47:39)
ものは試しにDLLへ渡すパスの文字列を前後に十分な変更されても問題ないメモリではさんで渡してみたら
どうです??できればローカル変数ではなく、グローバルな十分な大きさを持つ配列、あるいは構造体の
メンバーに保持させてそれを渡すのです。DLL側で文字列ポインタを受け取っている場合はそれがどんな
領域へのポインタかを吟味せずに書き換えている可能性があります。C++はそれを安易に許すタイプの言
語ですから・・・・。ここまでの状況をみてると、ただ単に潜在的なバグが表面に現れただけのように思
えます。

引用返信 編集キー/
■60882 / inTopicNo.12)  Re[2]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Ys (7回)-(2011/07/22(Fri) 14:13:18)
No60880 (todo さん) に返信

todo さん
返信ありがとうございます。

>>'System.StackOverflowException'は無限ループ等で発生する例外だと思うのですが、
>>もともと.NET Framework3.5では問題なく動いていたように、無限ループにはなっていないと思っています。
>
> 無限再帰呼び出しとか。
> デバックで例外が発生したときに「呼び出し履歴」を見れば分かります。

呼び出し履歴は確認しましたが、『btn_clickイベント → ShowDialog』しかなく無限ループに入っている様子はありません。


引用返信 編集キー/
■60883 / inTopicNo.13)  Re[8]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Ys (8回)-(2011/07/22(Fri) 14:50:02)
No60881 (ロートルプログラマ さん) に返信

ロートルプログラマ さん
返信ありがとうございます。

> ものは試しにDLLへ渡すパスの文字列を前後に十分な変更されても問題ないメモリではさんで渡してみたら
> どうです??できればローカル変数ではなく、グローバルな十分な大きさを持つ配列、あるいは構造体の
> メンバーに保持させてそれを渡すのです。DLL側で文字列ポインタを受け取っている場合はそれがどんな
> 領域へのポインタかを吟味せずに書き換えている可能性があります。C++はそれを安易に許すタイプの言
> 語ですから・・・・。

現在以下のような状態です。
@DLLアクセスクラスの中でメンバ変数をstring型で宣言(変数Aと変数B)
A変数Aにフォルダパス、変数BにXMLファイルパスを設定
B設定した2つの変数を、DLLで引数に設定
CDLL側ではchar*で受け取り処理を実行
DDLLが正常に終了し、変数Bを使ってXMLファイルから情報を取得

すいません、理解力がなく・・・これでは不十分でしょうか?


> ここまでの状況をみてると、ただ単に潜在的なバグが表面に現れただけのように思
> えます。

正直、その可能性が高いと思っているのですが(ノ_-;)
じゃあなぜ、.NET Framework3.5がOKで、4で出るようになったかがわからず。。。

引用返信 編集キー/
■60884 / inTopicNo.14)  Re[1]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ くり太郎 (32回)-(2011/07/22(Fri) 15:12:52)
くり太郎 さんの Web サイト
No60820 (Ys さん) に返信
> 開発環境:VisualStudio2010
> 使用言語:C#
>
> 初めて投稿させていただきます。
> 全くの初心者ではないですが、知識はすごく浅いので、ご迷惑をおかけすると思いますが、よろしくお願い致します。
>
>
> もともと.NET Framework3.5で開発していたシステムの対象のフレームワークを、.NET Framework4に変更しました。
> ビルドは問題なく通るのですが、システムを起動すると以下のコマンドで例外が発生するようになってしまいました。
>
> if( Dlg.ShowDialog( this ) == DialogResult.OK )
> ※"Dlg"はSystem.Windows.Forms.Formを継承して作成した画面になります。

とりあえず、別に新規プロジェクトを作って、現象を再現させながらシンプル化させていきながら原因箇所を調べていくのが良いと思います。
.NET Framework 3.5 から 4 に変更させただけで StackOverflowException 例外というのは考えにくいですよねぇ・・・

開発環境は 64 bit ですか?
引用返信 編集キー/
■60890 / inTopicNo.15)  Re[2]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ ロートルプログラマ (3回)-(2011/07/22(Fri) 20:10:19)
なーんだ、話は単純じゃないですか。たぶん。

>DDLLが正常に終了し、変数Bを使ってXMLファイルから情報を取得

DLL側でchar *で受けてるString 変数B はC#が期待するような返し方はしませんよ。たぶん。
変数B をいわゆるbyte型の配列で十分な大きさに確保して渡してください。あ、これはDLLが
変数Bを変更してるという場合ですが。書き込みの文脈からするとDLL側で変数Bを変更するよ
うに見えます。C++とC#は名前は似ていますが全く違うものだと考えたほうがいいと思います。
char *というのはC++では単なるメモリのアドレス(番地)です。その番地を使って好きなように
内容を書き換えることがC++ではできます。例としてはchar *ptr; ptr[-1] = 'A';というC++
のコードはptrが保持するメモリのアドレス-1をASCIIコードのAで書き換えます。ptrが指す
アドレスがアクセスできないアドレスであればアクセス違反でプログラムは停止させられますが、
アクセスが許されたアドレスであれば平気で書き換えます。その書き換えた結果がエラーとして
現れるのかどうかは特定できません。
引用返信 編集キー/
■60891 / inTopicNo.16)  Re[3]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Azulean (793回)-(2011/07/22(Fri) 23:53:23)
1 度、C++ での関数宣言と現状の C# での DllImport の宣言を書いてもらったら話は早そうな気がしました。

# .NET 3.5 vs 4 の違いは推測がつかないけれども。
引用返信 編集キー/
■60912 / inTopicNo.17)  Re[4]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Ys (9回)-(2011/07/25(Mon) 10:33:29)
返信が遅くなって申し訳ありません。


■No60884 (くり太郎 さん) に返信

くり太郎 さん
返信ありがとうございます。

> とりあえず、別に新規プロジェクトを作って、現象を再現させながらシンプル化させていきながら原因箇所を調べていくのが良いと思います。
> .NET Framework 3.5 から 4 に変更させただけで StackOverflowException 例外というのは考えにくいですよねぇ・・・

新規プロジェクトを作成してテストしてみました。
以下のようなテストをしてみたのですが結果は同じでした。
@メインフォームのボタンをクリックし、空っぽのダイアログを表示したLoadイベントで、DLLコールを実施(現在の状態とほぼ同じ) → ダイアログを閉じたときにShowDialogでStackOverflowException例外発生
Aメインフォームのボタンをクリックし、DLLコール → コール終了後、メイン画面に戻った際にApplication.RunでStackOverflowException例外発生
もう少しいろいろと試してみようと思います。

> 開発環境は 64 bit ですか?

開発環境は32bitです。


■No60890 (ロートルプログラマ さん) に返信

ロートルプログラマ さん
返信ありがとうございます。

> DLL側でchar *で受けてるString 変数B はC#が期待するような返し方はしませんよ。たぶん。
> 変数B をいわゆるbyte型の配列で十分な大きさに確保して渡してください。あ、これはDLLが
> 変数Bを変更してるという場合ですが。書き込みの文脈からするとDLL側で変数Bを変更するよ
> うに見えます。

すいません、私の書き方がわかりづらかったみたいで。。。
DLLで変数Bの変更はしていません。
変数BにはXMLファイルのパスセットして、そのXMLファイルにDLL内の処理であるファイル情報を書き込んでいます。
その後、変数Bにセットしてあったファイルパスを利用し、XMLファイルから内容を取得しています。


■No60891 (Azulean さん) に返信

Azulean さん
返信ありがとうございます。

> 1 度、C++ での関数宣言と現状の C# での DllImport の宣言を書いてもらったら話は早そうな気がしました。
> # .NET 3.5 vs 4 の違いは推測がつかないけれども。

<C#>
	[DllImport("OutPut.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
	private extern static int _OutPutData( string CheckPathA, string CheckPathB, string XmlFile );

	//DLLコール
	int nRet = _OutPutData( Path, string.Empty, XmlFile );

<C++>
	int OutPutData(char* CheckPathA, char* CheckPathB, char* XmlFile)

このような感じです。
※CheckPathBは使用していないため、string.Emptyで渡しています。
ちなみに、DllImport宣言で、.NET Framework3.5では『CallingConvention = CallingConvention.Cdecl』は書いていませんでしたが、
.NET Framework4では、PInvokeStackImbalanceが検出されるため、追記しました。

引用返信 編集キー/
■60914 / inTopicNo.18)  Re[5]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ む (1回)-(2011/07/25(Mon) 12:33:19)
> CallingConvention = CallingConvention.Cdecl

StdCallかWinapiなのでは無かろうか?
DLL側の作りは分かりませんが、本当にCdecl?
間違ってたらスタック飛ぶかも知れませんね。

参考
http://msdn.microsoft.com/ja-jp/library/system.runtime.interopservices.callingconvention(v=vs.80).aspx
Cdecl:呼び出し元がスタックを消去します。
これを使用すると、varargs で関数を呼び出すことができます。Printf など、受け取るパラメータの数が可変のメソッドで使用します。

StdCall:呼び出し先がスタックを消去します。これは、プラットフォーム呼び出しでアンマネージ関数を呼び出すための既定の規約です。

Winapi:このメンバは実際には呼び出し規約ではありません。
代わりに、既定のプラットフォーム呼び出し規約を使用します。たとえば、Windows では StdCall、Windows CE .NET では Cdecl が既定値になります。
引用返信 編集キー/
■60915 / inTopicNo.19)  Re[6]: .NetFramework3.5から4に変更すると例外発生
□投稿者/ Ys (10回)-(2011/07/25(Mon) 13:41:33)
No60914 (む さん) に返信

む さん
返信ありがとうございます。

>>CallingConvention = CallingConvention.Cdecl
>
> StdCallかWinapiなのでは無かろうか?
> DLL側の作りは分かりませんが、本当にCdecl?
> 間違ってたらスタック飛ぶかも知れませんね。

StdCallやWinapiにすると、PInvokeStackImbalanceが検出されるため、Cdeclとしている状況なのです。
確かに「受け取るパラメータの数が可変のメソッド」ではないので、StdCallやWinapiのような気もするのですが。。。

引用返信 編集キー/
■60917 / inTopicNo.20)  Re[7]: .NetFramework3.5から4に変更すると例外発生
 
□投稿者/ む (2回)-(2011/07/25(Mon) 23:06:12)
DLLの方で関数に__stdcall付けてますか?
呼出規約は付けてなければcdecl、あればstdcallのはず。

MSDNより:
CallingConvention フィールドの既定値は WinAPI です。この場合の既定の呼び出し規約は StdCall です。
http://msdn.microsoft.com/ja-jp/library/system.runtime.interopservices.dllimportattribute.callingconvention

これより、3.5まではCallingConventionの指定なし:既定の呼出 ->Winapi = StdCallで呼び出していた。
4の場合、「PInvokeStackImbalance」の回避目的でCdeclを指定 -> 呼出規約が変わってスタックが・・・ -> 例外発生?
と思うんですけど、どうでしょう?

ついでにこんな情報も有るようです。

VisualStudio2010から、MDA(Managed Debugging Assistants)がデフォルトで有効になりました。
MDAは、ランタイムイベントに関するメッセージを発生させ、マネージコードからアンマネージコードへの遷移時に発生する検出が難しいバグを分離できる機能です。
PInvokeStackImbalanceは、このMDAによって検出されます。
・・・
PInvokeStackImbalanceが検出されても、問題が露呈せず動作します。
(PInvokeStackImbalanceを発生させ、食い違ったスタックの処理を.NETがうまくやります。)
そのため、PInvokeStackImbalanceを無効にするという方法が取られることがありますが、もっと良い方法があります。
それは、C#コンパイラに、MeCabのコンパイラの呼出規約を教えることです。
・・・
http://wiki.sh4e.net/?Tips%2FOther%2FMeCab

MDA pInvokeStackImbalance の無効化 ― CLR 2.0 でのデバッグ実行 (2)
http://d.hatena.ne.jp/NyaRuRu/20051224/p1
引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -