4

最近、サーバー アプリケーション (Windows サービス) の 1 つが OutOfMemory 例外で失敗したことがわかりました。何が起こっているのかを調べようとしましたが、ファイナライズ キュー内のオブジェクトがファイナライズされていないため、ガベージ コレクションが発生しません。Windbg を使用して、どのファイナライザーがこの動作を引き起こす可能性があるかを調べようとしましたが、どのオブジェクトが原因であるかを正確に特定することはできません。

!finalizequeue コマンドを使用すると、次のことがわかります。

    0:053> !ファイナライズキュー
    clr.dll の PDB シンボルがロードされていません
    クリーンアップする SyncBlocks: 0
    リリース予定のフリースレッド インターフェイス: 0
    リリースされる MTA インターフェイス: 0
    解放される STA インターフェイス: 0
    ----------------------------------
    ジェネレーション 0 には 28 個のファイナライズ可能なオブジェクトがあります (050eab4c->050eabbc)
    ジェネレーション 1 には 15 個のファイナライズ可能なオブジェクトがあります (050eab10->050eab4c)
    第 2 世代には 658 個のファイナライズ可能なオブジェクトがあります (050ea0c8->050eab10)
    ファイナライズの準備完了 3027 オブジェクト (050eabbc->050edb08)
    ...

3027 は信じられないほど高い数値です (数分間実行した後ですが、この数値はまだ増加しており、決して低下していません)。アドレス 050eabbc にあるオブジェクトを見つけようとしましたが、常に異なるタイプなので、それが原因ではないと思います。

ファイナライザー スレッドのネイティブ コール スタックを出力しようとすると、次のようになりました。

    0:053> ~2k
    *** エラー: シンボル ファイルが見つかりませんでした。C:\Windows\SYSTEM32\KERNELBASE.dll のシンボルをエクスポートするようにデフォルト設定 -
    ChildEBP RetAddr  
    警告: スタック アンワインド情報は利用できません。次のフレームは間違っている可能性があります。
    032ef09c 772f10b4 ntdll!ZwWaitForSingleObject+0xc
    *** エラー: シンボル ファイルが見つかりませんでした。C:\Windows\SYSTEM32\combase.dll のシンボルをエクスポートするようにデフォルト設定 -
    032ef0b0 755ff0b5 カーネルベース!WaitForSingleObject+0x12
    032ef0e4 7554b22a コンベース!NdrOleDllGetClassObject+0x1399
    032ef108 755ff10c コンベース!PropVariantCopy+0x177b
    032ef224 75511724 コンベース!NdrOleDllGetClassObject+0x13f0
    032ef27c 7558115d コンベース!DcomChannelSetHResult+0x17c7
    032ef2d8 755fd39a コンベース!CoRegisterSurrogateEx+0x3494
    *** エラー: シンボル ファイルが見つかりませんでした。C:\Windows\SYSTEM32\RPCRT4.dll のシンボルをエクスポートするようにデフォルト設定 -
    032ef2f4 76a9e4a0 コンベース!NdrExtStubInitialize+0x21a9
    032ef71c 755fc779 RPCRT4!NdrComplexArrayUnmarshall+0xcac
    032ef738 75510d77 コンベース!NdrExtStubInitialize+0x1588
    032ef748 755816d5 コンベース!DcomChannelSetHResult+0xe1a
    032ef7dc 75587aa5 compase!CoRegisterSurrogateEx+0x3a0c
    *** エラー: シンボル ファイルが見つかりませんでした。C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll のシンボルをエクスポートするようにデフォルト設定 -
    032ef82c 748ab680 コンベース!StringFromIID+0x28d
    032ef92c 748ab758 clr!PreBindAssemblyEx+0x259d
    032ef964 7487960d clr!PreBindAssemblyEx+0x2675
    032ef980 748ab55a clr!GetMetaDataInternalInterfaceFromPublic+0x2162a
    032ef9dc 74878915 clr!PreBindAssemblyEx+0x2477
    032efa2c 7487887c clr!GetMetaDataInternalInterfaceFromPublic+0x20932
    032efa44 7478a5e2 clr!GetMetaDataInternalInterfaceFromPublic+0x20899
    032efa8c 74777d71 clr!GetPrivateContextsPerfCounters+0x968

ファイナライザー スレッドは常に ZwWaitForSingleObject でスタックしているため、これはファイナライザー スレッドがスタックしているという別の手がかりです。

私の質問は、どのオブジェクトがファイナライザー キューのスタックを引き起こしているかを調べるにはどうすればよいかということです。面白いことに、私はファイナライザーをまったく使用していません:-(

4

1 に答える 1

5

私の「サイキック デバッグ」の推測では、STA スレッドで実行される一部のコードは COM オブジェクトを作成しますが、その STA スレッドはメッセージ ポンピングに関する COM 規則に従っていません (そして、おそらくスレッドは完全になくなっています)。これを言っているのは、ファイナライザーのコール スタックに Combase があるからです。明らかに、適切なシンボルが必要であり、ネイティブ コール スタックとマネージ コール スタックの両方を確認する必要があります。

.symfix C:\localsymbolcache .reload ~2s kb !clrstack

この質問を復活させたい場合は、結果を投稿してください。

于 2014-08-25T07:49:45.093 に答える