5

プログラムが閉じられた後にのみ例外をスローするように見えるアプリケーションがあります。そして、それは非常に矛盾しています。(一貫性のないバグがいかに楽しいかは誰もが知っています...)

私の推測では、クリーンアップ プロセス中にエラーが発生しました。しかし、これらのメモリの読み取り/書き込みエラーは、「安全でない」コードの使用法 (ポインタ?) に何か問題があることを示しているようです。

私が興味を持っているのは、これらの状況をデバッグするための最良の方法は何ですか?
既に終了したプログラムをどのようにデバッグしますか?
より大きな問題を分解するための出発点を探しています。

これらのエラーは、いくつかの方法で表示されるようです (実行時、デバッグ時など)。

1: .NET-BroadcastEventWindow.2.0.0.0.378734a.0: Application.exe - アプリケーション エラー
「0x03b4eddb」の命令が「0x00000004」のメモリを参照していました。メモリに「書き込み」できませんでした。 2: Application.vshost.exe - アプリケーション エラー
「0x0450eddb」の命令が「0x00000004」のメモリを参照していました。メモリに「書き込み」できませんでした。 3: Application.vshost.exe - アプリケーション エラー
「0x7c911669」の命令が「0x00000000」のメモリを参照していました。メモリを「読み取る」ことができませんでした。 4: Application.vshost.exe - アプリケーション エラー
「0x7c910ed4」の命令は、「0xfffffff8」のメモリを参照していました。メモリを「読み取る」ことができませんでした。
4

6 に答える 6

6

AcrobarReader COM コンポーネントを使用してこの問題が発生しました。時々、アプリケーションの終了後、「Application.vshost.exe - アプリケーション エラー」「メモリを読み取れませんでした」というメッセージが表示されました。GC.Collect() と WaitForPendingFinalizers() は役に立ちませんでした。

私の google-fu は、このページに私を導きました: http://support.microsoft.com/kb/826220。私の場合、方法 3 を変更しました。

プロセス エクスプローラーを使用すると、AcroPDF.dll が Main 関数の最後の行の前に解放されていないことがわかりました。というわけで、ここから 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 に対して変更できます。新しいバグが発生しないことを願うばかりです。

于 2010-08-09T09:48:54.077 に答える
4

アプリがマルチスレッドの場合、適切に終了せず、破棄されたオブジェクトにアクセスしようとしているワーカー スレッドからエラーが発生する可能性があります。

于 2008-10-08T13:54:01.777 に答える
1

「一貫性のない」という言い回しは「非決定論的」です。そして、.NET環境では非決定論的に何が起こりますか?オブジェクトの破壊。

これが私に起こったとき、犯人は私が外部APIへの安全でない呼び出しをラップするために書いたクラスにいました。オブジェクトがスコープ外になったときにコードが呼び出されることを期待して、クラスのデストラクタにクリーンアップコードを配置しました。しかし、それは.NETでのオブジェクト破棄の動作方法ではありません。オブジェクトがスコープ外になると、そのオブジェクトはファイナライザーのキューに入れられ、ファイナライザーがそれに近づくまでそのデストラクタは呼び出されません。プログラムが終了するまでこれを行わない場合があります。これが発生した場合、結果はここで説明しているものとよく似たものになります。

クラスにを実装させ、それが終わったときにオブジェクトIDisposableを明示的に呼び出すと、問題は解決しました。Dispose()(IDisposableを実装するもう1つの利点は、usingブロックの開始時にオブジェクトをインスタンス化でき、コードがブロックを離れるときにDispose()が確実に取得できることです。)

于 2008-10-08T18:52:21.503 に答える
1

最近、このようなエラーをよく見かけます。私の問題は、.NET ランタイムと対話する CRT (C ランタイム) が終了プロセスをクリーンアップする方法に関連していました。私のアプリケーションは C++ であるため複雑ですが、C# で記述された COM アドインを読み込むことができます。

これをデバッグするには、ネイティブ デバッグを使用する必要があると思います。Visual Studio (混合モードのデバッグに設定) または WinDbg。Microsoft パブリック シンボル サーバーを使用して Windows コンポーネントの PDB をダウンロードする方法を調べてください。これらのシンボルが必要になります。

私たちの問題の多くは、.NET の (ひどい) COM クライアント サポートにありました。カウントを正しく参照していないので(開発者側で多くの作業をせずに)ひどいと言います。ガベージ コレクションが実行されるまで、COM オブジェクトは参照されず、ゼロまでカウントダウンされませんでした。これにより、シャットダウン中に奇妙なタイミングの問題が発生することがよくあります。

于 2008-10-08T13:18:34.563 に答える
0

提案されたコードを使用した後、エラーは表示されなくなりました。

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
于 2010-05-14T15:08:05.743 に答える
0

プログラムの制御下でバグを強制的に発生させるには、これを試してください

   //set as many statics as you can to null;
   GC.Collect();
   GC.WaitForPendingFinalizers();
} //exit main
于 2008-11-24T20:21:31.103 に答える