最近、メンテナンス性のために構造化プログラミング手法を使用して作業プロトタイプライブラリを書き直しました。アプリケーションのCOMベースのAPIを使用して、サードパーティのアプリケーション(TPA)からデータにアクセスします。 APIはWin32メッセージング(WM_COPYDATA)を使用してTPAと通信します。COM相互運用機能を使用して.NETアプリケーションでAccessViolationExceptionがランダムに発生する
新しいライブラリコード:
- は、Visual Studio 2010 SP1でC#で書かれています。
- ターゲット.NET Framework 4(プロトタイプで3.5でした)。
- 匿名メソッドと新しいカスタムジェネリッククラスを使用して、元のコードを分解し単純化します。これは、どちらも使用しません(ただし、HashSet <>などの.NET Frameworkユーティリティタイプは除きます)。
- 組み込みの相互運用型(埋め込みInterop Types = False)と登録不要のCOM(Isolated = True)を使用するCOMベースのAPIを参照してください。
- Marshal.ReleaseComObjectを使用して、COMベースのAPIによって返されるオブジェクトによる確定的なメモリ管理を実現します。
- COMベースのAPIは、シングルスレッドアパートメント(COMベースのAPIはアパートメントスレッド)で実行されるワーカースレッドでのみ使用されます。
- COMベースのAPIを呼び出すときに初期バインディングを使用します。
私たちのテスターアプリケーションは、COMベースのAPIのAccessViolationExceptionでランダムにクラッシュします。スタックトレースは、これがUnsafeNativeMethods.DispatchMessageW(下記のサンプルを参照)またはCOMベースのAPIのいくつかの異なるプロパティのいずれかで発生することを示しています。テスターアプリケーションは、メニュー、ステータスバー、およびRichTextBoxを備えた単純なWinFormsアプリケーションです。
この動作は、FinalReleaseComObjectでReleaseComObjectを置き換えるかどうかにかかわらず、ワーカースレッドとUIスレッド間のスレッド間通信が有効かどうかに関係なく、Windows XPおよびWindows 7に共通です。 TPAが非常に忙しいとき、より頻繁にクラッシュするようです。それが始まっている間。
プロトタイプライブラリはVS 2008を使用して開発されました。プロジェクトをVS 2010に変換した後でも、プロトタイプアプリケーションはクラッシュしません。
System.AccessViolationExceptionが処理されませんでした。メッセージ=しようとしました 保護されたメモリを読み書きします。これは、しばしば他の メモリが壊れていることを示しています。 Source = System.Windows.Forms StackTrace:at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG & msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID、のInt32理由、のInt32 pvLoopData) System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(のInt32 理由、ApplicationContextの文脈において) System.Windows.Forms.Application.ThreadContext.RunMessageLoop(のInt32 理由、ApplicationContextの文脈で) at System.Windows.Forms.Application.Run(フォームmainForm) at IndexerTester.Program.Main()D:\ TestApps \ Indexer \ IndexerTester \ Program.cs:行17
同じような問題が発生しましたか?
原因を特定するためのアドバイスや潜在的な回避策はありますか?
コールスタックは、ワーカースレッドからメインスレッドにマーシャリングされているコールを示します。 STAスレッドでCOMオブジェクトを作成する場合、STAが動作します。しかし、これは問題ではないでしょう。ネイティブコードでは、C#プログラムからAVでの爆弾の助けが必要なことはめったにありません。アンマネージデバッグを有効にしなかったため、何も表示されません。 –
ありがとう、私はこの呼び出しスタックがスレッド間マーシャリングを表すのか分かりませんでした。残念ながら、私は管理されていないデバッグに慣れていません。 COMソースコードやそのPDBファイルにアクセスできないので、私はそれを使用できるかどうかはわかりません。あなたはこれを行う方法を学ぶためのいくつかのリソースを提案できますか? – groverboy
これらのリソースがなくてもほとんどできません。クラッシュを再現するための単体テストを作成します。そしてコードの所有者に送って助けてもらいましょう。 –