質問
プログラムを閉じた後にのみ例外をスローするように見えるアプリケーションがあります。そして、それは非常に矛盾しています。 (私たちは皆、一貫性のないバグがどれほど楽しいか知っています...)
私の推測では、クリーンアッププロセス中にエラーが発生しました。しかし、これらのメモリ読み取り/書き込みエラーは、私の「安全でない」部分で何か間違っていることを示しているようです。コードの使用法(ポインター?)。
私が興味を持っているのは、これらの状況をデバッグする最良の方法です。
既に閉じているプログラムをどのようにデバッグしますか?
より大きな問題を解決するための出発点を探しています。
これらのエラーは、いくつかの方法(実行時、デバッグ)で現れます:
1: .NET-BroadcastEventWindow.2.0.0.0.378734a.0: Application.exe - Application Error
The instruction at "0x03b4eddb" referenced memory at "0x00000004". The memory could not be "written". 2: Application.vshost.exe - Application Error
The instruction at "0x0450eddb" referenced memory at "0x00000004". The memory could not be "written". 3: Application.vshost.exe - Application Error
The instruction at "0x7c911669" referenced memory at "0x00000000". The memory could not be "read". 4: Application.vshost.exe - Application Error
The instruction at "0x7c910ed4" referenced memory at "0xfffffff8". The memory could not be "read".
解決
アプリがマルチスレッドの場合、適切に終了せず、破棄されたオブジェクトにアクセスしようとしないワーカースレッドからエラーが発生する可能性があります。
他のヒント
AcrobarReader COMコンポーネントを使用してこの問題が発生しました。時々、アプリケーション終了後に" Application.vshost.exe-Application Error"がありました。 「メモリを読み取れませんでした」。 GC.Collect()とWaitForPendingFinalizers()は役に立ちませんでした。
私のgoogle-fuは、このページに私を導きます: http://support.microsoft.com/kb / 826220 。ケース3の方法を変更しました。
プロセスエクスプローラーを使用して、Main関数の最後の行の前にAcroPDF.dllがリリースされないことがわかりました。それで、ここにAPI呼び出しがあります。
DLLImports(DLLImportはSystem.Runtime.InteropServices名前空間にあります):
<DllImport("kernel32.dll", EntryPoint:="GetModuleHandle", _
SetLastError:=True, CharSet:=CharSet.Auto, _
CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function GetModuleHandle(ByVal sLibName As String) As IntPtr
End Function
<DllImport("kernel32.dll", EntryPoint:="FreeLibrary", _
SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function FreeLibrary(ByVal hMod As IntPtr) As Integer
End Function
そしてアプリケーションの終了前:
Dim hOwcHandle As IntPtr = GetModuleHandle("AcroPDF.dll")
If Not hOwcHandle.Equals(IntPtr.Zero) Then
FreeLibrary(hOwcHandle)
Debug.WriteLine("AcroPDF.dll freed")
End If
この手順は、他の不適切なdllに合わせて変更できます。新しいバグが発生しないことを願っています。
最近、このようなエラーがたくさん見られました。私の問題は、CRT(Cランタイム)が.NETランタイムと相互作用して終了プロセスをクリーンアップする方法に関連していました。私のアプリケーションはC ++であるという事実によって複雑になっていますが、COMアドインをロードできます。一部はC#で記述されています。
これをデバッグするには、ネイティブデバッグを使用する必要があると思います。 Visual Studio(混合モードデバッグに設定)またはWinDbg。 Microsoftパブリックシンボルサーバーを使用してWindowsコンポーネント用のPDBをダウンロードする方法を調べてください。これらのシンボルを 必要 します。
問題の多くは、.NETの(ひどい)COMクライアントサポートにありました。 (開発者側で多くの作業をせずに)参照カウントが正しく参照されないため、私はひどいと言います。ガベージコレクションが完了するまで、COMオブジェクトはゼロまで参照カウントされませんでした。これにより、シャットダウン中に奇妙なタイミングの問題が発生することがよくあります。COMオブジェクトは、本来あるべき長い時間後にクリーンアップされます。
&quot; inconsistent&quot;のより凝った言葉は「非決定的」です。そして、.NET環境で非決定論的に何が起こるのでしょうか?オブジェクトの破壊。
これが私に起こったとき、犯人は外部APIへの安全でない呼び出しをラップするために書いたクラスにありました。クラスのデストラクタにクリーンアップコードを配置し、オブジェクトがスコープ外になったときにコードが呼び出されることを期待しました。しかし、それは.NETでのオブジェクトの破壊の仕組みではありません。オブジェクトがスコープ外に出ると、ファイナライザーのキューに入れられ、ファイナライザーが到達するまでデストラクタは呼び出されません。これは、プログラムが終了するまで実行されません。これが発生した場合、結果はここで説明しているものとよく似ています。
クラスに IDisposable
を実装させ、処理が完了したときにオブジェクトで Dispose()
を明示的に呼び出すと、問題はなくなりました。 (IDisposableを実装するもう1つの利点は、 using
ブロックの開始時にオブジェクトをインスタンス化し、コードがブロックを離れたときにDispose()が取得されることを確信できることです。)
これを試して、プログラムの制御下でバグを強制的に発生させます
//set as many statics as you can to null;
GC.Collect();
GC.WaitForPendingFinalizers();
} //exit main
提案されたコードを使用した後、エラーが表示されなくなりました:
GC.Collect();
GC.WaitForPendingFinalizers();