c ++ - Betydning af 'RtlpAnalyzeHeapFailure' i vinduet med et dump

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg arbejder med at følge adgangsbrud:


Unhandled exception at 0x77DB2A10 (ntdll.dll) in <Process>.exe.dmp: 
0xC0000005: Access violation reading location 0x184487B8. occurred


Kildekoden ser ud som følger:


Result CParameter::SetValue(..., ..., <internal\_Class>* pBlock, ...)
{
  ...
  <internal\_Class>* pStore = nullptr;
  if (!pBlock)
  {
    pStore = &m\_Data; // m\_Data is a global variable
  }
  else pStore = pBlock;

  if (pStore->pbData)
  {
    pStore->Clear(); // here we have the crash
  }


Opkaldsstakken ser ud som følger:


   ntdll.dll!\_RtlpCoalesceFreeBlocks@16()  Unknown Non-user code. Symbols loaded.
   ntdll.dll!@RtlpFreeHeap@16()    Unknown Non-user code. Symbols loaded.
   ntdll.dll!\_RtlFreeHeap@12() Unknown Non-user code. Symbols loaded.
   ole32.dll!CRetailMalloc\_Free(IMalloc * pThis=0x777476bc, void * pv=0x1842de40) Line 687  C++ Non-user code. Symbols loaded.
   ole32.dll!CoTaskMemFree(void * pv=0x1842de40) Line 475   C++ Non-user code. Symbols loaded.
=> <Process>.exe!CParameter::SetValue(..., <internal\_Class> * pBlock=0x00000000, ...) Line 5528 C++ Symbols loaded.


I vinduet ser jeg følgende værdi for &m\_Data:


0x77e4f9ae {Inside ntdll.dll!\_RtlpAnalyzeHeapFailure@12()} {pbData=0xd2b70f3d <Error reading characters of string.> ...}


Mere information:



  • Værdien af ​​pBlock er NULL

  • Værdien af ​​pStore er ukendt af debuggeren



spørgsmål:



  • Hvor er funktionen 'Ryd ()' i opkaldsstakken?

  • Hvad med værdien 'RtlpAnalyzeHeapFailure' i uret-vinduet? Betyr det, at min dump er så meget beskadiget, at jeg ikke kan få nyttige oplysninger ud af det?



Tak på forhånd

Bedste reference



  Hvor er funktionen 'Ryd ()' i opkaldsstakken?



Det ser ud som om det var indlejret.



  Værdien af ​​pStore er ukendt af debuggeren



Er det stadig fra m\_Data?


Hvis du kigger på koden i nærheden af ​​nedbrudspunktet, kan du se, hvilket register det har været i for nylig, og hvis det er bevaret, skal du kunne se det gemt på et tidspunkt.


Fejlen skyldes, at hukommelsessystemet registrerer, at hukommelsen er forkert frigjort. Det kan være, at m\_Data har en flydende værdi eller allerede blevet slettet.


Jeg har lavet en lignende funktion.


\_\_declspec(noinline) void Type::Clear()
{
    delete pbData;
    pbData = nullptr;
}

\_\_declspec(noinline) void SetValue(Type * pBlock)
{
    Type * pStore = nullptr;
    if (!pBlock)
    {
        pStore = &m\_Data; // m\_Data is a global variable
    }
    else pStore = pBlock;

    if (pStore->pbData)
    {
        pStore->Clear(); // here we have the crash
    }
}


Dens demontering (fra windbg) er: -


0:000:x86> uf debugging2!SetValue
debugging2!Type::Clear [c:sourceexampledebugging2debugging2.cpp @ 17]:
   17 01041020 56              push    esi
   17 01041021 8bf1            mov     esi,ecx
   18 01041023 6a00            push    0
   18 01041025 ff36            push    dword ptr [esi]
   18 01041027 e85c000000      call    debugging2!operator delete (01041088)
   18 0104102c 83c408          add     esp,8
   19 0104102f c70600000000    mov     dword ptr [esi],0
   19 01041035 5e              pop     esi
   20 01041036 c3              ret

debugging2!SetValue [c:sourceexampledebugging2debugging2.cpp @ 23]:
   23 01041040 833df833040100  cmp     dword ptr [debugging2!m\_Data (010433f8)],0
   31 01041047 740a            je      debugging2!SetValue+0x13 (01041053)  
Branch

debugging2!SetValue+0x9 [c:sourceexampledebugging2debugging2.cpp @ 33]:
   33 01041049 b9f8330401      mov     ecx,offset debugging2!m\_Data (010433f8)
   33 0104104e e9cdffffff      jmp     debugging2!Type::Clear (01041020)  Branch

debugging2!SetValue+0x13 [c:sourceexampledebugging2debugging2.cpp @ 35]:
   35 01041053 c3              ret  Branch


Dette viser (i mit tilfælde) opkaldet til Clear () er blevet erstattet af et hop, skjul det fra stakken med en optimering.
Dette viser også at ecx ved adressen 01041049 er lastet med værdien for opkaldet.
MSDN: x86-opkaldskonventioner
Ecx er ikke en bevaret værdi, så vi ville ikke kunne finde den værdi, den holdt (bortset fra det ser ud til at være &m\_Data fra dine kommentarer). [12]


Men vi kan se på funktionerne på stakken ...


I :: Clear funktionen flyttes ecx til esi. Så esi (som er bevaret) har nu samme værdi.


Kigger på den næste funktion (operator sletning),


debugging2!operator delete 
 [f:ddvctoolscrtvcstartupsrcheapdelete\_scalar\_size.cpp @ 14]:
   14 01041088 55              push    ebp
   14 01041089 8bec            mov     ebp,esp
   15 0104108b ff7508          push    dword ptr [ebp+8]
   15 0104108e e890030000      call    debugging2!operator delete (01041423)
   15 01041093 59              pop     ecx
   16 01041094 5d              pop     ebp
   16 01041095 c3              ret


Vi ser esi er ikke ændret eller reddet. Så vi kigger på den næste funktion på stakken ....


0: 000: x86> uf 01041423
Flow analyse var ufuldstændig, nogle kode kan mangle
    debugging2! operator delete
    [[f: \ dd \ vctools \ crt \ vcstartup \ src \ heap \ delete\_scalar.cpp @ 15]]:
       15 01041423 e982090000 jmp debugging2! Free (01041daa) Branch


I hvert tilfælde søger vi esi for at blive gemt et sted på stakken, så vi kan finde det ...