windbg / sos: поиск того, какой класс имеет статическую ссылку на объект - PullRequest
3 голосов
/ 20 октября 2011

Я устраняю утечку памяти и обнаружил, что объект удерживается в памяти, потому что на него ссылается словарь.Когда я делаю! Gcroot для экземпляра словаря, единственный закрепленный дескриптор - это массив System.Object [], который сам по себе не рутирован:

0:025> !gcroot -nostacks 38ad01f8
DOMAIN(0000000002287D80):HANDLE(Pinned):11e15c0:Root:  00000000123c5018(System.Object[])->
  0000000002f2ab20(System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[MyApp.MyObject, MyApp]])->
  000000004223e6e0(System.Collections.Generic.Dictionary`2+Entry[[System.String, mscorlib],[MyApp.MyObject, MyApp]][])->
  0000000038ad01f8(MyApp.MyObject)

Это приводит меня к выводу, что экземпляр Dictionary удерживаетсястатическим полем в некотором классе (.NET хранит все ссылки на статические поля в массиве объектов).

Однако теперь я застрял, потому что! gcroot и! refs (из sosex) не видят ссылки на статические поля.

Я могу искать в куче указатель на адрес 2f2ab20:

0:025> s-q 0 L?0xbfffffff 2f2ab20
00000000`123c76f8  00000000`02f2ab20 00000000`02f2ab78

Так что я вижу, что какая-то структура около адреса 123c76f8 ссылается на мой словарь.Но куда мне идти отсюда?Структура около 123c76f8 должна указываться структурой EEClass, но sos / sosex, кажется, не предоставляет способ определить, какой EEClass является релевантным.

Без этой информации, как я могу выяснить, какой объект содержитстатический словарь?

Ответы [ 3 ]

3 голосов
/ 19 июля 2013

Один из вариантов такого анализа - использовать библиотеку ClrMD на NuGet, чтобы написать небольшую программу для выполнения дампа или процесса.

Программа будет выглядеть следующим образом:

    DataTarget dataTarget = DataTarget.LoadCrashDump(@"c:\path\to\crash.dmp");
    ClrRuntime runtime = dt.CreateRuntime(@"c:\path\to\mscordacwks.dll");
    ClrHeap heap = runtime.GetHeap();

    foreach (ClrRoot root in heap.EnumerateRoots())
    {
        if (root.Object == 0x0000000002f2ab20)
        {
            Console.WriteLine(root.Kind);
            if (root.Kind == GCRootKind.StaticVar)
                Console.WriteLine(root.Name);
        }
    }

Подробнее о библиотеке ClrMD можно прочитать в блоге DotNet

1 голос
/ 16 июля 2013

Я запускаю код, который публикуется в этом блоге .

версия: Win7 X64 .NET 4

DOMAIN(000000000007E9D0):HANDLE(Pinned):1a17f8:Root:  0000000012381018(System.Object[])->
  0000000002391dc0(System.Collections.ArrayList)->
  0000000002391e78(System.Object[])->
  0000000002391e60(StaticRootedWhere.Fruit)



0:000> s-d 0000000012381018 L?0x2000 0000000002391dc0
00000000`12382fd8  02391dc0 00000000 0238fb30 00000000  ..9.....0.8.....


0:000> s-d 0 L?0xffffffffffffffff 00000000`12382fd8
00000000`00319680  12382fd8 00000000 02009443 00000000  ./8.....C.......
000007ff`000337d8  12382fd8 00000000 00000001 00000000  ./8.............
000007ff`00150160  12382fd8 00000000 24548b48 278ee828  ./8.....H.T$(..'




0:000> !u 000007ff`00150160
Normal JIT generated code
StaticRootedWhere.Program..cctor()
Begin 000007ff00150120, size 59

E:\..........\StaticRootedWhere\Program.cs @ 11:
000007ff`00150120 4883ec38        sub     rsp,38h
000007ff`00150124 48b8f0340300ff070000 mov rax,7FF000334F0h
000007ff`0015012e 8b00            mov     eax,dword ptr [rax]
000007ff`00150130 85c0            test    eax,eax
000007ff`00150132 7405            je      StaticRootedWhere!StaticRootedWhere.Program..cctor()+0x19 (000007ff`00150139)
000007ff`00150134 e817ac51ee      call    clr!JIT_DbgIsJustMyCode (000007fe`ee66ad50)
000007ff`00150139 488d0d58ff07ec  lea     rcx,[mscorlib_ni+0x4d0098 (000007fe`ec1d0098)]
000007ff`00150140 e81b2d0bee      call    clr!JIT_TrialAllocSFastMP_InlineGetThread (000007fe`ee202e60)
000007ff`00150145 4889442420      mov     qword ptr [rsp+20h],rax
000007ff`0015014a 488b442420      mov     rax,qword ptr [rsp+20h]
000007ff`0015014f 4889442428      mov     qword ptr [rsp+28h],rax
000007ff`00150154 488b4c2428      mov     rcx,qword ptr [rsp+28h]
000007ff`00150159 e802b7f5eb      call    mscorlib_ni!System.Collections.ArrayList..ctor() (000007fe`ec0ab860)
000007ff`0015015e 48b9d82f381200000000 mov rcx,12382FD8h
000007ff`00150168 488b542428      mov     rdx,qword ptr [rsp+28h]
000007ff`0015016d e88e270bee      call    clr!JIT_WriteBarrier_Fast (000007fe`ee202900)
000007ff`00150172 eb00            jmp     StaticRootedWhere!StaticRootedWhere.Program..cctor()+0x54 (000007ff`00150174)
000007ff`00150174 4883c438        add     rsp,38h
000007ff`00150178 c3              ret

Я публикую свой результат здесь только для вашегоссылка.это мой второй раз, чтобы проверить результат после прочтения блога.При первой проверке не получается ожидаемый результат.

0 голосов
/ 20 октября 2011

Один метод описан в этом блоге .Краткое объяснение метода заключается в том, что вы хотите найти кусочек кода, который добавил новый элемент в массив объектов.Этот массив объектов является массивом статических полей (00000000123c5018 в вашем случае).Предполагается, что именем метода будет AnOffendingType..ctor (), который является искомым конструктором типа, который вы ищете.

...