web-dev-qa-db-ja.com

System.AccessViolationExceptionの原因を見つける

アプリケーションで奇妙な致命的なSystem.AccessViolationExceptionが発生します。例外をログに記録するようにAppDomain.CurrentDomain.UnhandledExceptionイベントを構成したため、これらが表示されます。

Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at Bootstrap.Run() in e:\build-dir\src\Bootstrap.cs:line 25

例外自体には、メッセージ「保護されたメモリの読み取りまたは書き込みを試みました。他のメモリが破損している可能性があります。」

  • 問題の原因を突き止めるには、どのような手順を踏めばよいでしょうか。
  • クラッシュの原因となった不正なアドレスまたはポインタ値を特定する方法はありますか?
  • 問題の原因となっているネイティブライブラリコードを特定できますか?
  • 有効にできるデバッグ/トレースは他にありますか?

[〜#〜]更新[〜#〜]

  • これは、WinForms APIの以前の非スレッドセーフな使用が原因である可能性がありますか?
30
chillitom

発生しているのは、「プログラムで問題が発生したため、終了します」とまったく同じですが、OSではなく.NETランタイムによって捕捉されます。

スタックトレースを見ると、コードによってトリガーされていないため、使用しているライブラリまたはカスタムコントロールによって生成されたワーカースレッドからのものであると思います。

このようなものを追跡する唯一の方法は、デバッガーの下でネイティブライブラリを実行することです。デバッガーは、CLRレイヤーに到達する前にアクセス違反をトラップする必要があります。これは簡単なことも難しいこともあります。

ネイティブコードが独自のプロジェクトである場合、これを設定する最も簡単な方法は、.NETプロジェクトとC++プロジェクトの両方を同じソリューションに配置し、.NETプロジェクトがC++プロジェクトを参照していることを確認することです。環境の詳細を投稿していただければ、より具体的なアドバイスをさせていただく場合があります。

6
Mike Caron

スタックトレースがネイティブディスパッチメッセンジャーのMSGパラメータの不正なデータを指しています。Microsoftからシンボルをロードし、そのスタックトレースのパラメータを確認してみましたか?.

UIのコントロールと接続しているイベントを知らなければ、問題が何であるかを正確に判断することは困難です。

3
Steve Mitcham

私は同様の問題を抱えており、@ BartReadとは一貫して異なります。私にとって、いくつかのCLIコードは単純なWindowsフォームアプリで正常に機能していましたが、それをララガープラグインエコシステム(マルチスレッド)に配置すると、Application.RunまたはApplication.DoEventsでポンプする必要があるメッセージが表示されました。ポンプされているコードにアクセスできる場合、最善の策(私にとってうまくいったこと)は、機能を維持しながらコードのより多くの部分をコメント化することでした。私はGC :: Allocをコールバック/デリゲートしていなかったことが判明し、固定され、参照されている間、メモリ内で移動されたか、コレクションのフラグが立てられました。

gC Allocを使用する場合は、自分でクリーンアップしてください。

3
David

aDOを使用してストアドプロシージャを実行すると、この問題が発生しました。このエラーには2つの原因があります。

  1. 接続文字列が正しくありません。
  2. パラメータタイプのミスマッチ(db-int32の場合はlong、短い方のnvarchar(10)にlongを渡す)
2
Apex ND

スタックトレースは何も教えてくれません: 。例外がなくなった場合、パッケージを更新して確認できますか?Workerthreadからプロパティにアクセスするときに、None-Threadsafe Com-ObjectsでSystem.AccessViolationExceptionを確認しました。例外は、一部のAPIの以前の非スレッドセーフバージョンを使用したことが原因です。

---(Attributes を追加して状況に対処しました

[HandleProcessCorruptedStateExceptions]
[SecurityCritical]

メソッドに、COMオブジェクトからこれらの競合するプロパティにアクセスします。また、私は追加する必要がありました

<legacyCorruptedStateExceptionsPolicy enabled="true" />

私のapp.configに設定すると、これらの例外をキャッチして賢く処理することができました。

詳細情報 破損した状態の例外MSドキュメント 破損した状態の例外を処理し、プロセスをシャットダウンしないことにより、「CLRはプログラムの正確さとメモリの安全性についてかなり強力な保証を提供します」という道を離れます。

クレジット https://stackoverflow.com/a/4759831/1196586

0
gReX