LoginSignup
0
3

More than 5 years have passed since last update.

.NET Framework で COM を書くと CLR の Access Violation が発生するときは InterfaceTypeAttribute を書き忘れていないか確認するべし

Last updated at Posted at 2019-01-18

前提

.NET Framework で CoClass を実装して登録し,そのクラスが外部のアプリケーションから呼び出される。

こねくりまわした環境

.NET Framework 4.5
Windows 10 (x64)

結論

interface の宣言に, InterfaceTypeAttribute を設定していなかった。

だめだったコード

[ComImport]
[Guid(~~~~)]
public interface Hoge
{
  // ~~~~~
}

呼び出し元プロセスに Visual Studio でアタッチするとこのような例外が表示された。
AccessViolation.png

うまくいったコード

[ComImport]
[Guid(~~~~)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface Hoge
{
  // ~~~~~
}



以下,解決までの経緯

落ちる

C# で COM に登録するクラスを作って実験していたところ,特定のタイミングで呼び出し元のアプリケーションが落ちる。
C# で書いた部分に問題があると考え,try-catch など普段通りデバッグを行ってみるも,これらのすべてに到達せずに落ちる。何の前触れもなく。

デバッガを接続してみる

Visual Studio をそのプロセスに接続してから実験を行うと,このような表示が。
AccessViolation.png

:thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking:

落ちるタイミングの特定

実験を続けていたら,少なくともこのタイミングで落ちるということが特定できたので,コードを減らして実験をしたところ,
C# で書いたクラスのインスタンスを COM を通して外部から呼び出されるように登録するコードを実行しない,あるいは登録後すぐに登録を解除したところ,落ちないことが分かった。

見つける

登録メソッドに渡す引数の型を確認して,渡すクラスの宣言を確認し,インターフェースの確認をしたところで, InterfaceTypeAttribute をこのインターフェースだけ書き忘れていることがわかり,書き加えたところ登録をしてもアクセス違反が発生しなくなった。

場合によってはアクセス違反にならず,別のメソッドが呼ばれる可能性?

自分の場合は,後ろから3番目のメソッドが呼び出されるときにアクセス違反になっていたのだが,メソッドが4つ以上あるインターフェースの,最初に書かれたメソッドが呼び出されるような場合はもしかすると4番目のメソッドが呼び出されるかもしれない。

IUnknownQueryInterface, AddRef, Release の3つを持っているため,3つずれた結果,自分の場合は存在しない領域を参照してしまっていたのではないかと考えている。[要検証] Access Violation した。よくわからない。

0
3
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
0
3