LoginSignup
31
17

Access violationに惑わされて4時間奪われた話

Last updated at Posted at 2017-07-21

あらすじ

C#で外部の端末との連携開発をしていて、OCXをWindows Formに貼りつけ1、event発火処理部分のDebugしているときに、ブレークポイントに引っかからず「vshost32.exe は動作を停止しました」なんていうダイアログが出て、スタックトレースも見れない状況で困っていた。

困ったらとりあえずGoogle

仕方なくVisual Studioの出力ウィンドウを見ていたら、インジケータが出ているときにキャンセルボタンを押したとき2に、こんな1行があった。

プログラム '[3284] TestApp.vshost.exe' はコード -1073741819 (0xc0000005) 'Access violation' で終了しました。

「Access violation」?なんだコイツは……と思ってググる。
要約すると、

保護されたメモリの読み取りまたは書き込みが試行されたときにスローされる例外。

ということらしい。
ああOCXはC++みたいなもんだし(勝手な解釈)、メモリ周りの問題あるある……と思ったものの、そもそもOCXは端末作ってる会社から提供されたものだし、こっちのコードの問題の可能性が高いと思い、ググり直し。
「C# OCX Access Violation」「OCX event access violation」「windows form access violation」…のように、ひたすらググって、英文読んで(Goolge翻訳大先生を使ったけど)、コード書き換えて、試行錯誤して……

……直らん。

考え方を変えて、「AccessViolationExceptionの中身を見よう」という方向へ。
と言ってもこの考え方が後回しになったのは理由があって、ググってる途中に以下の記事を見つけて、この方向は無いなと自己完結してしまったから。

AccessViolationExceptionを捕捉できるようにする

要約すると、

  • .NET Framework 3.5 以前は AccessViolationException を catch できていたが、.NET Framework 4 以降ではできなくした。
  • すでにメモリアクセス違反が発生してしまったものを復旧しつつ挙動させることは極めて困難だから、中途半端になって2次災害を引き起こすよりも突然の死を選ぶ方が安全である。

まあそらそうだ……と。

結局

でもブレークポイントで止めて内容を確認するぐらいならいいだろと、「debug AccessViolationException」みたいにググった一番上……
c# - How to debug AccessViolationException coming from native code - Stack Overflow

Project + Properties, Debug tab, tick "Enable unmanaged code debugging".

ん?こんな簡単に?まあやってみるか。
「プロジェクトのプロパティ>デバッグ>ネイティブ コードのデバッグを有効にする(T)」にチェック
ビルドして動かしてみるけど、まあ無理かな…

……

直った。

vshost32.exeが強制終了しなくなった。
4時間3が1クリックで済むレベルだったなんて……

ここでテスト

  • ネイティブ コードのデバッグを有効にする(T)
  • Visual Studio ホスティング プロセスを有効にする(O)

→ NG

  • ネイティブ コードのデバッグを有効にする(T)
  • Visual Studio ホスティング プロセスを有効にする(O)

→ OK

  • ネイティブ コードのデバッグを有効にする(T)
  • Visual Studio ホスティング プロセスを有効にする(O)

→ OK

つまり、vshost32.exeっていう名前のVisual Studioホスティングプロセスが悪さをしていたということ……なのかな。ただ、どんな悪さをしていたのかまでは調べる気力が尽きました。

ちなみに

UserControlをクラスライブラリ、Windows FormをWindowsアプリケーション、というように別プロジェクトで作ったんですが、変えたのはWindowsアプリケーションのほうのプロジェクトで、クラスライブラリのプロジェクトは変えてないです。

………いまどきOCX周りで困る人って少数なんじゃないかな(偏見)

追記(2022/08/03)

View数的に、特殊な内容ではあるものの、結構困ってる人がいるみたい。

  1. 正確にはOCXを貼りつけたUserControlをWindorsFormに貼りつけた。OCXを直接使う部分はUserControlにコードを書いて、WindowsFormはUserControlのインターフェースメソッドを呼び出す。

  2. インジケータが消えてデバッグするかそのまま終了するか選べるようになって終了を押したら、「プログラム '[12488] TestApp.vshost.exe' はコード 255 (0xff) で終了しました。」が出てきた。

  3. この記事書くのに1時間使ったので正確には5時間です。

31
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
17