Windows7 x64上でVisual C# 2010 Expressを使ってとあるプログラムを開発。開発マシン上では何の問題もなかったのに、実行ファイルをXP x86に持って行くと、ウィンドウを表示することもなくエラーで落ちる。理由は不正なアドレス(0x4)へのアクセス。また対象フレームワークの問題 かと思ったのですが、今回はフレームワークを変更しても解決しない。
こまめにログを出力させて突き止めたエラー発生箇所はForm1.InitializeComponent…Visual C#が自動コード生成した場所じゃないか。さらにInitializeComponentの内部を探ると、落ちた箇所は最後の方にあるthis.panel1.ResumeLayout(false);という行。デバッガで追ってもResumeLayoutを記述しているコードはなく、.NET Frameworkの中っぽい。
何がおかしいのか見当もつかないので、以下の手順で変更、その都度XP上で落ちるかどうかを確認。
- Form1.panel1上に配置していたコントロールを別の場所に退避、panel1を削除 → 落ちない
- panel1をつくり直すが、元にあったコントロールはpanel1上に配置しない → 落ちない
- 新panel1上に退避していたコントロールを配置 → 落ちない
- pane1のプロパティでSizeChangedイベントに自前のハンドラを設定 → 落ちた
- 自前のイベントハンドラを何もしない関数に変更 → 落ちない
この自前ハンドラはpanel1のサイズに合わせて中のコントロールサイズを複雑に変えるものでして、panel1とpanel1上のコントロールのサイズを参照するため、コントロールの初期化が終わる前(=InitializeComponentが完了する前)に呼び出されたなら確かにまずい。しかしWindows7 x64のデバッガ上ではハンドラは呼び出されないんだけどなぁ。
解決策としては、- panel1のプロパティでのSizeChangedイベントハンドラの指定をしない
- Form1_Loadでイベントハンドラを指定する
[2010/11/6 追記] どうもWindows7とXPでコントロールの表示サイズが異なることが原因みたいです。今回のプログラムはWindows7で開発していたので、
- XPで実行: panel1にアンカー(メインウィンドウのサイズに合わせて自身のサイズを変更する)が設定されており、panel1.ResumeLayoutでリサイズが発生、ハンドラが呼び出され落ちる
- 7で実行: 開発時のサイズで表示できるのでリサイズが発生しない
ということは、XPで開発するとVista/7では落ちることになるのかな…
1. hoge — 2010/11/11@08:42:00
まさにこの現象だったようで対策ができ助かりました。
(Lunaの有無でコントロールの表示サイズが違っていたのが原因だったようです)