- - PR -
マネージ・アンマネージの相互コールバックに関して
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-03-06 12:22
C++/CLIにて、以下のようなサンプルを使いテストしたのですが、AccesViolationが発生してしまいます。
Stepでデバグしたところ、登録したコールバックも呼ばれてはいるのですが、 CallbackProcから、returnしたところでAccessViolationが発生します。 試しに、CallbackProcを以下のように変更したところ、 何の問題もなく処理が完了しました。
MSDNの”C++ Interop を使用してコールバックおよびデリゲートをマーシャリングする” 中のサンプルを参考にこのサンプルを作成したのですが、なぜ、一度ローカル変数に値を代入した上で、それを返さないと、AccessViolationが発生のか理解できず困っております。 もしご存じの方がいらっしゃいましたら、御教授の程宜しくお願いいたします。 環境: Visual Studio 2005 Professional /clrスイッチ付きでコンパイル。 [ メッセージ編集済み 編集者: NetSeed 編集日時 2007-03-06 13:48 ] | ||||||||
|
投稿日時: 2007-03-06 12:44
呼び出し規約が違うとか。
>typedef int (*proc)(int hoge); を typedef int (__stdcall *proc)(int); // もしくは WINAPI、CALLBACK としてみるとどうでしょうか? [ メッセージ編集済み 編集者: Blue 編集日時 2007-03-06 12:47 ] | ||||||||
|
投稿日時: 2007-03-06 13:14
Blueさん、返信ありがとうございます。
これで試したところ、問題なく動きました。 呼び出し規約の差異でエラーが起きることは理解できるのですが、 ローカル変数に一度代入し、それを返すことによって、 エラーを回避できるのか、理解が出来ておりません。 もし、ご存じでしたら御教授いただけないでしょうか? | ||||||||
|
投稿日時: 2007-03-06 13:26
GetFunctionPointerForDelegate の「英語の」ヘルプには、
なので、Blue さんの指摘されているように、__stdcall をつけることで解決するわけですが... ハングアップの理由は、スタックポインタがずれてしまうからです。 __stdcall(古くはPASCALコールと呼ばれていた)と、_cdecl コール(C標準形式)では、コールスタックのクリア方法がことなります。 これが、ローカル変数への代入を伴ったことにより結果的にスタックの利用状況が変わり、クラッシュしないように見えているだけにすぎません。 もし、まわりにアセンブラに詳しい人がいたらその人にレクチャーしてもらうとよいかと。 _________________ // とっちゃん(高萩 俊行)@わんくま同盟 // とっちゃん’Blog // MS-MVP for Developer Tools - Visual C++ // WindowsInstallerの話題はhttp://www.freeml.com/msiまで | ||||||||
|
投稿日時: 2007-03-06 13:48
とっちゃんさんご返信ありがとうございます。
あくまで、見かけてうまく動いてるように見えるだけカモしれないと言うことですね。 いずれにせよ、windows.hにて、CALLBACKが__stdcallとdefineされている以上、 それを使うべきなのだとおもいました。 御教授ありがとうございました。 | ||||||||
|
投稿日時: 2007-03-06 16:53
「かも」ではなく、偶発的に問題が露見していないだけです。もしかしたら別のコードを挟んだら同じように問題が発生するかもしれませんよ。
windows.h の CALLBACK の定義が __stdcall なのは、そのほうがバイナリサイズが小さくなるからです。 #x86アーキテクチャの場合は、速度も若干早くなるとおもいますが、今時のCPUだとどうなんだろう? なので、大半がコールバック関数に CALLBACK をつけていますが、全てがそうなっているわけではないということにも注意が必要です。 特に今回の __stdcall が必要な理由とは全然関係ない部分ですので。 今回は、日本語ドキュメント側で __stdcall 形式で返されるという部分が欠落してしまっていることが不具合発生の主な要因とおもわれます。 英語のドキュメントを読め!とはいいませんが、少しでもあやふやな点があれば、英語ドキュメントを参照する、最終的な確認は英語ドキュメントで行うというように癖をつけていけば、おそらく発生しなかったであろうとおもわれます。 とはいえ、バグはバグですので、プログラムを直すということと一緒に、今後同じ問題で後輩や新米開発者がはまらないように、MSDN フォーラムにフィードバックすることをお勧めします。 MSDNのドキュメントが修正されれば、同じ問題で悩む人は確実に減ると思いますので。 _________________ // とっちゃん(高萩 俊行)@わんくま同盟 // とっちゃん’Blog // MS-MVP for Developer Tools - Visual C++ // WindowsInstallerの話題はhttp://www.freeml.com/msiまで | ||||||||
|
投稿日時: 2007-03-06 17:18
確認を最後まで行っていれば、自分で解決できたかもしれないと思うと、 汗顔の至りです。。。 誤訳、というわけではないですが、必要な記載事項が漏れていることが あり得ると考えておかなければならないと思いました。 MSDNのフォーラムには、折を見てフィードバックするつもりです。 |
1