私のプログラムは、catch(Exception e)
ブロックでは処理できないエラーをスローし、クラッシュします。
アクセス違反破損状態例外。
これは奇妙なことです。私が知っているように、破損した状態の例外はアンマネージコードからスローされますが、ここでは StringBuilder メソッドを呼び出すときにこの例外が発生します。
コードはバックグラウンドスレッドで実行され、ときどきクラッシュし、簡単に再現することはできません。だから私はプロセスに WinDbg をアタッチし、例外の次のスタックを持っています:
_000000001dabd8c8 000007feea129a1d [HelperMethodFrame: 000000001dabd8c8]
000000001dabda00 000007fee90cfce8 System.Text.StringBuilder.ExpandByABlock(Int32)
000000001dabda40 000007fee90cfba4 System.Text.StringBuilder.Append(Char*, Int32)
000000001dabdaa0 000007fee9102955 System.Text.StringBuilder.Append(System.String, Int32, Int32)
000000001dabdaf0 000007ff00bf5ce3 MineUtils.Common.Strings.Strings.Replace(System.String, System.String, System.String, Boolean, Boolean)
000000001dabdb90 000007ff00bf5a59 MineUtils.Common.Strings.Strings.RemoveSubstrings(System.String, System.String, System.String, Boolean) [D:\Programs\Visual Studio 2005 Projects\MineUtils.Common\Strings\Strings.Common-Main.cs @ 1481
_
WinDbgは、この例外が発生したことを示しています。
_EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 000007feea129a1d (clr!WKS::gc_heap::find_first_object+0x0000000000000092)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000003d80
Attempt to read from address 0000000000003d80
_
そのような例外はメソッド属性[HandleProcessCorruptedStateExceptions]で処理できると読みましたが、StringBuilderのみを使用しているのにこの例外が発生するのはなぜですか?
これは以前のWinDbg分析です(StringBuilder.ToString()
は例外を引き起こします):
_*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
FAULTING_IP:
clr!WKS::gc_heap::find_first_object+92
000007fe`ea129a1d f70100000080 test dword ptr [rcx],80000000h
EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 000007feea129a1d (clr!WKS::gc_heap::find_first_object+0x0000000000000092)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000001
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000001c98
Attempt to read from address 0000000000001c98
ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
EXCEPTION_PARAMETER1: 0000000000000000
EXCEPTION_PARAMETER2: 0000000000001c98
READ_ADDRESS: 0000000000001c98
FOLLOWUP_IP:
clr!WKS::gc_heap::find_first_object+92
000007fe`ea129a1d f70100000080 test dword ptr [rcx],80000000h
MOD_LIST: <ANALYSIS/>
NTGLOBALFLAG: 0
APPLICATION_VERIFIER_FLAGS: 0
MANAGED_STACK:
(TransitionMU)
000000001AB7DFC0 000007FEE90CFE07 mscorlib_ni!System.Text.StringBuilder.ToString()+0x27
000000001AB7E010 000007FF00C750A9 SgmlReaderDll!Sgml.Entity.ScanToken(System.Text.StringBuilder, System.String, Boolean)+0x169
000000001AB7E080 000007FF00C760E6 SgmlReaderDll!Sgml.SgmlDtd.ParseParameterEntity(System.String)+0xc6
000000001AB7E0F0 000007FF00C76FD8 SgmlReaderDll!Sgml.SgmlDtd.ParseModel(Char, Sgml.ContentModel)+0x298
000000001AB7E160 000007FF00C7701C SgmlReaderDll!Sgml.SgmlDtd.ParseModel(Char, Sgml.ContentModel)+0x2dc
000000001AB7E1D0 000007FF00C7701C SgmlReaderDll!Sgml.SgmlDtd.ParseModel(Char, Sgml.ContentModel)+0x2dc
000000001AB7E240 000007FF00C76BA5 SgmlReaderDll!Sgml.SgmlDtd.ParseContentModel(Char)+0x65
000000001AB7E290 000007FF00C763D7 SgmlReaderDll!Sgml.SgmlDtd.ParseElementDecl()+0xe7
000000001AB7E320 000007FF00C747A1 SgmlReaderDll!Sgml.SgmlDtd.Parse()+0xc1
000000001AB7E370 000007FF00C73EF5 SgmlReaderDll!Sgml.SgmlDtd.Parse(System.Uri, System.String, System.IO.TextReader, System.String, System.String, System.Xml.XmlNameTable)+0x175
000000001AB7E410 000007FF00C73B33 SgmlReaderDll!Sgml.SgmlReader.LazyLoadDtd(System.Uri)+0x163
000000001AB7E480 000007FF00C737B9 SgmlReaderDll!Sgml.SgmlReader.OpenInput()+0x19
000000001AB7E4E0 000007FF00C7334C SgmlReaderDll!Sgml.SgmlReader.Read()+0x1c
000000001AB7E530 000007FEE5983C4C System_Xml_ni!System.Xml.XmlLoader.Load(System.Xml.XmlDocument, System.Xml.XmlReader, Boolean)+0xac
000000001AB7E590 000007FEE5983730 System_Xml_ni!System.Xml.XmlDocument.Load(System.Xml.XmlReader)+0x90
...
000000001AB7F0A0 000007FEE97ED792 mscorlib_ni!System.Threading.Tasks.Task.Execute()+0x82
000000001AB7F100 000007FEE90A181C mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0xdc
000000001AB7F160 000007FEE97E7F95 mscorlib_ni!System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef)+0x1b5
000000001AB7F1E0 000007FEE97E7D90 mscorlib_ni!System.Threading.Tasks.Task.ExecuteEntry(Boolean)+0xb0
000000001AB7F220 000007FEE90EBA83 mscorlib_ni!System.Threading.ThreadPoolWorkQueue.Dispatch()+0x193
000000001AB7F2C0 000007FEE90EB8D5 mscorlib_ni!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()+0x35
(TransitionUM)
EXCEPTION_OBJECT: !pe 2a61228
Exception object: 0000000002a61228
Exception type: System.ExecutionEngineException
Message: <none>
InnerException: <none>
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 80131506
MANAGED_OBJECT_NAME: System.ExecutionEngineException
MANAGED_STACK_COMMAND: _EFN_StackTrace
LAST_CONTROL_TRANSFER: from 000007feea12bce4 to 000007feea129a1d
ADDITIONAL_DEBUG_TEXT: Followup set based on attribute [Is_ChosenCrashFollowupThread] from Frame:[0] on thread:[PSEUDO_THREAD]
FAULTING_THREAD: ffffffffffffffff
DEFAULT_BUCKET_ID: INVALID_POINTER_READ_CALL
PRIMARY_PROBLEM_CLASS: INVALID_POINTER_READ_CALL
BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_READ_WRONG_SYMBOLS_CALL__SYSTEM.EXECUTIONENGINEEXCEPTION
_
UPDATED AGAIN
ページヒープ を有効にした後の例外のWinDbgスタックは次のとおりです。
_ (1480.e84): Access violation - code c0000005 (first chance)
ntdll!ZwTerminateProcess+0xa:
00000000`77c415da c3 ret
0:023> !clrstack
OS Thread Id: 0xe84 (23)
Child SP IP Call Site
0000000037ded848 0000000077c415da [HelperMethodFrame: 0000000037ded848]
0000000037dedab0 000007fee9effd17 System.Text.StringBuilder.ToString()*** WARNING: Unable to verify checksum for C:\Windows\Assembly\NativeImages_v4.0.30319_64\mscorlib\8f7f691aa155c11216387cf3420d9d1b\mscorlib.ni.dll
0000000037dedb00 000007ff00cceae9 Sgml.Entity.ScanToken(System.Text.StringBuilder, System.String, Boolean)
0000000037dedb70 000007ff00cd19b2 Sgml.SgmlDtd.ParseAttDefault(Char, Sgml.AttDef)
0000000037dedbc0 000007ff00cd120b Sgml.SgmlDtd.ParseAttDef(Char)
0000000037dedc00 000007ff00cd1057 Sgml.SgmlDtd.ParseAttList(System.Collections.Generic.Dictionary`2<System.String,Sgml.AttDef>, Char)
0000000037dedc50 000007ff00cd10cd Sgml.SgmlDtd.ParseAttList(System.Collections.Generic.Dictionary`2<System.String,Sgml.AttDef>, Char)
0000000037dedca0 000007ff00cd0e9a Sgml.SgmlDtd.ParseAttList()
0000000037dedd10 000007ff00cce1f1 Sgml.SgmlDtd.Parse()
0000000037dedd60 000007ff00ccd945 Sgml.SgmlDtd.Parse(System.Uri, System.String, System.IO.TextReader, System.String, System.String, System.Xml.XmlNameTable)
0000000037dede00 000007ff00ccd582 Sgml.SgmlReader.LazyLoadDtd(System.Uri)
0000000037dede70 000007ff00ccd1f9 Sgml.SgmlReader.OpenInput()
0000000037deded0 000007ff00cccd8c Sgml.SgmlReader.Read()
0000000037dedf20 000007fee67b3bfc System.Xml.XmlLoader.Load(System.Xml.XmlDocument, System.Xml.XmlReader, Boolean)*** WARNING: Unable to verify checksum for C:\Windows\Assembly\NativeImages_v4.0.30319_64\System.Xml\8e4323f5bfb90be4621456033d8b404b\System.Xml.ni.dll
*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\Assembly\NativeImages_v4.0.30319_64\System.Xml\8e4323f5bfb90be4621456033d8b404b\System.Xml.ni.dll
0000000037dedf80 000007fee67b36e0 System.Xml.XmlDocument.Load(System.Xml.XmlReader)
[deleted]
0000000037deea90 000007feea61d432 System.Threading.Tasks.Task.Execute()
0000000037deeaf0 000007fee9ed17ec System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
0000000037deeb50 000007feea617c35 System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef)
0000000037deebd0 000007feea617a30 System.Threading.Tasks.Task.ExecuteEntry(Boolean)
0000000037deec10 000007fee9f1b953 System.Threading.ThreadPoolWorkQueue.Dispatch()
0000000037deecb0 000007fee9f1b7a5 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
0000000037def310 000007feeae4dc54 [DebuggerU2MCatchHandlerFrame: 0000000037def310]
0:023> !verifyheap
-verify will only produce output if there are errors in the heap
The garbage collector data structures are not in a valid state for traversal.
It is either in the "plan phase," where objects are being moved around, or
we are at the initialization or shutdown of the gc heap. Commands related to
displaying, finding or traversing objects as well as gc heap segments may not
work properly. !dumpheap and !verifyheap may incorrectly complain of heap
consistency errors.
object 000000000e34caf8: bad member 000000001024b9a0 at 000000000e34cb08
curr_object: 000000000e34caf8
Last good object: 000000000e34cab0
----------------
0:023> !analyze
Last event: 1480.e84: Exit process 0:1480, code 80131506
debugger time: Sun Sep 18 14:22:42.592 2011 (UTC + 1:00)
0:023> !analyze -v
Last event: 1480.e84: Exit process 0:1480, code 80131506
debugger time: Sun Sep 18 14:22:42.592 2011 (UTC + 1:00)
0:023> .do e34cab0
^ Syntax error in '.do e34cab0'
0:023> !do e34cab0
Name: System.String
MethodTable: 000007feea026870
EEClass: 000007fee9baed58
Size: 72(0x48) bytes
File: C:\Windows\Microsoft.Net\Assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: appliedFiltersContainer
Fields:
MT Field Offset Type VT Attr Value Name
000007feea02c758 4000103 8 System.Int32 1 instance 23 m_stringLength
000007feea02b298 4000104 c System.Char 1 instance 61 m_firstChar
000007feea026870 4000105 10 System.String 0 shared static Empty
>> Domain:Value 00000000021343a0:000000000db21420 <<
0:023> !do e34caf8
<Note: this object has an invalid CLASS field>
Name: System.Reflection.RuntimeAssembly
MethodTable: 000007feea02a128
EEClass: 000007fee9baf968
Size: 48(0x30) bytes
File: C:\Windows\Microsoft.Net\Assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007feea9ef7f0 4000e14 8 ...solveEventHandler 0 instance 0000000000000000 _ModuleResolve
000007feea036338 4000e15 10 ...che.InternalCache 0 instance 000000001024b9a0 m_cachedData
000007feea0259c8 4000e16 18 System.Object 0 instance 000000000e3abd18 m_syncRoot
000007feea033450 4000e17 20 System.IntPtr 1 instance 37a95f10 m_Assembly
_
それは何でしょうか?
最近、マネージヒープの破損に直面しましたが、これは私にとって新しいものでした。私はそれに非常に不満を抱いており、デバッグするためには多くのことを学ぶ必要がありました。最初に正しい方向性を教えてくれたSeva Titovに感謝します。彼の答えは簡潔でとても役に立ちました。問題をデバッグするために行ったアクションを自分の参照用にログに記録します。おそらくこれはこれに不慣れな他の人に役立つでしょう。
。NET 4でのヒープ破損のデバッグ:
ヒープの破損を疑う方法は?
簡単に:
アプリケーションは、適用された例外キャッチに関係なくランダムにクラッシュし、すべての例外をキャッチすることになっているcatch(Exception)
のようなブランケットを通過します。
アプリケーションのクラッシュダンプでCLRスタックを調べると、スタックの最上部にガベージコレクターが表示されます。
_000000001dabd8c8 000007feea129a1d [**HelperMethodFrame**: 000000001dabd8c8]
000000001dabda00 000007fee90cfce8 System.Text.StringBuilder.ExpandByABlock(Int32)
000000001dabda40 000007fee90cfba4 System.Text.StringBuilder.Append(Char*, Int32)
...
EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 000007feea129a1d (**clr!WKS::gc_heap**::find_first_object+0x0000000000000092)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000003d80
...
_
CLRスタックは常に異なるポイントを示します。例外が発生することが示されているStringBuilderのメソッドのように、クラッシュが発生したのか、表示されているコードが明らかに無関係であるのかは関係ありません。
詳細については、 。NETクラッシュ:アンマネージコードを呼び出すマネージヒープ破損。
段階的に進みます。前のステップが役に立たない場合、次の各ステップが使用されます。
ステップ1.コードを確認します。
安全でないコードまたはネイティブコードの使用についてコードを確認します。
unsafe
、DllImport
ステートメントのコードを確認します。PInvoke
のアプリケーションアセンブリを分析します。同様に、アプリケーションで使用されるサードパーティアセンブリを分析します。安全でないコードやネイティブコードの使用が見つかった場合は、それらに特に注意してください。このような場合のヒープの破損の最も一般的な原因は、バッファオーバーフローまたは引数の型の不一致です。ネイティブコードに入力するバッファが十分な大きさであること、およびネイティブコードに渡されるすべての引数が期待されるタイプであることを確認してください。
ステップ2.この破損状態の例外をキャッチできるかどうかを確認します。
このような例外を処理するには、catch(Exception)
ステートメントを含むメソッドを_[HandleProcessCorruptedStateExceptions]
_属性で修飾するか、以下を_app.config
_ファイルに適用する必要があります。
_<configuration>
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true" />
</runtime>
</configuration>
_
例外が正常にキャッチされた場合は、ログに記録して調べることができます。つまり、これは破損したヒープの問題ではありません。
破損したヒープ例外はまったく処理できません:HandleProcessCorruptedStateExceptionsが機能していないようです。
破損した状態の例外の詳細については、。NET4の破損した状態の例外のすべてを参照してください。
ステップ3.ライブデバッグ
このステップでは、本番環境(またはクラッシュを再現できる場所)でライブクラッシュするアプリケーションをデバッグします。
ダウンロードDebugging Tools for WindowsfromMicrosoft Windows SDK for Windows 7 and .NET Framework 4(aインストールする必要なコンポーネントを選択できるWebインストーラーがダウンロードされます(すべてのコンポーネントをマークします)。必要なデバッグツールの32ビットと64ビット(システムがx64の場合)バージョンの両方をインストールします。
ここでは、WinDbgをライブプロセスにアタッチする方法、クラッシュダンプを取得して調べる方法、ロード方法 [〜#〜] sos [〜#〜] WinDbgの拡張機能(google for詳細)。
デバッグヘルパーを有効にします。
Application Verifier(_C:\Program Files\Application Verifier
_-実行可能なコンパイルモードに応じてx86またはx64のいずれか必要なエディションを使用)を起動し、実行可能ファイルを左側のペインに追加し、右側のペインで1つのノード「Basics/Heaps」を確認します。変更を保存します。
グローバルフラグヘルパーを起動します(_C:\Program Files\Debugging Tools for Windows\gflags.exe
_-正しいエディション、x86またはx64を再度選択します)。 Global Flagsが開始されたら、[イメージファイル]タブに移動し、上部のテキストボックスにパスを含まない実行可能ファイルの名前を入力します(たとえば、 "MyProgram.exe ")。次に、 Tab キーを押して、次のボックスを設定します。
C:\Program Files\Debugging Tools for Windows (x64)\windbg.exe -g
)。詳細については、ヒープの破損、パート2を参照してください。
「コントロールパネル/システムとセキュリティ/システム」に移動します(または、スタートメニューの「コンピュータ」を右クリックして「プロパティ」を選択します。そこで「システムの詳細設定」をクリックし、表示されたダイアログの「詳細」タブに移動して、 「環境変数」ボタンをクリックします表示されたダイアログで、新しいシステム変数を追加します(システム管理者の場合-それ以外の場合はユーザー変数-この場合はログアウト/ログインする必要があります)必要な変数は「COMPLUS_HeapVerify」です値が "1"です。詳細については、スタックオーバーフローの質問。NET/C#:デバッグ環境変数COMPLUS_HeapVerify?を参照してください。
これでデバッグを開始する準備ができました。アプリケーションを起動します。 WinDbgが自動的に起動します。 WinDgbにクラッシュするまでアプリケーションを実行したままにして、ダンプを調べます。
[〜#〜] tip [〜#〜]:Global Flags、Application Verifierおよびデバッガーの添付設定、レジストリーで次のキーを削除します:x64-_HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\*YourAppName*
_
ステップ4. MDAを有効にします。
マネージデバッグアシスタントを使用してみてください。詳細はスタックオーバーフローの質問にありますヒープの破損を追跡するのに役立つMDAは何ですか?。
MDAはWinDbgと共に使用する必要があります。 Global FlagsおよびApplication Verifierと一緒に使用しました。
ステップ5. GCStressを有効にします。
アプリケーションがほとんど使用できなくなるため、GCStressを使用することは非常に重要なオプションですが、それでも問題ありません。詳細はGCStress:Windows 7でオンにする方法にあります。
ステップ6. x86用にコンパイルします。
アプリケーションが現在「任意のCPU」または「x64」プラットフォーム用にコンパイルされている場合、使用するプラットフォームに違いがない場合は、「x86」用にコンパイルしてみてください。これが誰かの問題を解決するために報告されているのを見ました。
ステップ7.コンカレントGCを無効にします-これは私のために機能しました
.NET 4で報告されている既知の問題がスレッドで報告されていますアンマネージモジュールのないgc_heap :: garbage_collectでの.NET 4ランタイムのアクセス違反。この問題は、_app.config
_ファイルで並行GCを無効にすることで解決できます。
_<?xml version="1.0"?>
<configuration>
<runtime>
<gcConcurrent enabled="false" />
</runtime>
</configuration>
_
ヒープの破損を管理しました。管理されたヒープの破損の問題の根本的な原因を見つけるのは簡単ではありません。問題は通常、ヒープが破損した後も長く続くためです。あなたの場合、StringBuilder
は赤いニシンです。汚職は以前に起こった。
私がすることは次のとおりです:
!VerifyHeap
を実行します。このようにして、破損が発生するコード内の場所をローカライズできる場合があります。WinDbgでコードを実行する場合は、偶発的な最初のチャンスAVに遭遇することに注意してください。 WinDbgをプロセスにアタッチしたら、sxd av
と入力して、セカンドチャンスAVのみを調査することをお勧めします。