|
Application에서 메모리 누수가 발생했는데, 원인을 찾을 수 없다는 case 는 빈번히 접할 수 있다. 다소 당황스러울 수 있지만, DebugDiag라는 Tool을 이용한다면, 쉽게 Allocation Thread stack을 tracking 할 수 있다. 이유는 leaktrack.dll이라는 injection DLL때문에 그것이 가능한데, 이로 인하여 DebugDiag Tool을 Allocation Stack sample이라는 형태로 간혹, leak으로 의심할 수 있는 Function Call을 Check 할 수 있게 한다. 하지만, Callstack이 간혹 너무 단순하거나 Callstack이 너무 복잡하고 길 경우에 일부 Function Call이 생략되는 경우가 발생한다. 혹, 생략된 Function이 Memory Leak을 Check 할 수 있는 중요한 Function 이라면 reporting된 정보가 의미 없어 질 수도 있는 것 아닌가. 하지만 방법이 없는 것은 아니다. 현재, DebugDiag 1.1 version에서 제공하는 Leaktrack.dll을 사용하는 경우 아래와 같은 방법을 통해서 보다 Detail 한 Thread Stack 에 대한 정보를 얻을 수 있다. 0:000> x leaktrack!* 0a437c74 LeakTrack!g_hLTHeap (<no parameter info>) 0a437c78 LeakTrack!g_TlsSlot (<no parameter info>) 0a437c7c LeakTrack!g_pMemoryManager (<no parameter info>) 0a437c80 LeakTrack!g_pHandleManager (<no parameter info>) 0a437c84 LeakTrack!g_hUnloadEvent (<no parameter info>) 여기서 주목해야 할 global variable 은 g_pMemoryManager 이다. 이놈이 thread stacks에 대한 정보를 메모리의 임의의 부분에 dumping 하고 있다. 그 위치를 찾아가보면, 0:000> !list -x "dds " -a "+4 l1" poi(LeakTrack!g_pMemoryManager)+3c 0a6d1f00 00000000 0a6d9244 4ed1c2da gdiplus!GpMemoryBitmap::AllocBitmapData+0x71 0a6d92ac 4ed3d893 gdiplus!GpMalloc+0x16 0a6d944c 747225c2 msctf!cicMemAllocClear+0x10 0a6d951c 74dae45b usp10!UspAllocCache+0x2b 0a6d992c 79e78bb2 mscorwks!EEHeapAlloc+0x12d 0a6d9994 7c9119e6 ntdll!RtlpAllocateDebugInfo+0x49 0a70a6f4 79e7495b mscorwks!EEVirtualAlloc+0x104 0a6d96bc 6e56231f msdtcprx!std::_Allocate<char>+0x17 이렇게 보여주는 list 들은 소위 Leaktrack에 의해서 tracking 되는 thread stack의 첫 번째 Funcation에 대한 address 이다. 그리고, 그 중 debugDiag report에서 이미 추정했던 Allocation이 눈에 띄게 많았던 첫번째 Funcation을 확인하여 해당 Funcation Call을 가지고 있는 Thread stack 정보들을 다음과 같이 쫓아갈 수 있다. 0:000> !list -x "dds " -a "+4 l1" poi(poi(poi(0a6d9244-4)+8)+4) 0a6d5b64 4ed3d893 gdiplus!GpMalloc+0x16 0b09fce4 4ecd211f gdiplus!GpFaceRealization::AllocateCache+0x21 0a6f0d74 4ecd2274 gdiplus!GpFaceRealization::IsMetricsCached+0x1d 0b0b0854 4ed3d893 gdiplus!GpMalloc+0x16 0b0a8834 4ecd30f5 gdiplus!GpFaceRealization::GetGlyphDataCached+0x1b 0b0ad15c 4ecd3448 gdiplus!GpFaceRealization::GetGlyphPos+0x16f 0b0ab2c4 4ecbd101 gdiplus!GpGraphics::DrawPlacedGlyphs+0x38e 0a6f48fc 7c910732 ntdll!RtlpAllocateFromHeapLookaside+0x42 0a705f54 7c9106ab ntdll!RtlAllocateHeap+0x1c2 0a6d575c 7c9106eb ntdll!RtlAllocateHeap+0xeac 0b0b299c 7c9106ab ntdll!RtlAllocateHeap+0x1c2 0a6d4dd4 7c9106eb ntdll!RtlAllocateHeap+0xeac 0a6fbf24 4ed181a2 gdiplus!GlyphImager::DrawGlyphs+0x14a 0a6d50a4 4ed1299f gdiplus!FullTextImager::DrawGlyphs+0x3da 0b0a66e4 4ecde261 gdiplus!DpRegion::Set+0x3b 0b0a6654 4ed7afad gdiplus!itrp_FDEF+0x190 0b09c974 4ed7654e gdiplus!itrp_Execute+0x1e7 0b0962f4 4ed14bd7 gdiplus!FullTextImager::GdipLscbkDrawGlyphs+0xe4 0a70b4bc 4ed284fa gdiplus!FmtText+0x5ce 0a6f3ffc 4ed285e9 gdiplus!DisplayText+0xc3 0a7023f4 4ed246a5 gdiplus!LsDisplayLine+0xfa 0a706fcc 4ed0fa1b gdiplus!BuiltLine::Draw+0x13 0a6f402c 4ed12eec gdiplus!FullTextImager::RenderLine+0x4d 0a70ade4 4ed13222 gdiplus!FullTextImager::Render+0x28e 0a70abec 4ed13337 gdiplus!FullTextImager::Draw+0xbe 0a70aba4 4ecbcd48 gdiplus!GpGraphics::DrawString+0x362 . . .너무 길어서 중간 생략한다. 해당 Windbg command 중에 poi(poi(0a6d9244-4)+8) 에 해당하는 address는 사실 Linked list의 header 부분에 해당한다. 이 말은 해당 Function Call(여기서는 gdiplus!GpMemoryBitmap::AllocBitmapData 이놈이 되겠다.)을 호출하는 thread stack이 단지 1개가 아니라는 것이다. 그러므로, 다음과 같은 방법을 통해 해당 Function call을 호출하는 다른 Thread stack에 대한 정보를 순차적으로 얻을 수 있다. !list -x "dds " -a "+4 l1" poi(poi(poi(0a6d9244-4)+8)+4) !list -x "dds " -a "+4 l1" poi(poi(poi(poi(0a6d9244-4)+8))+4) !list -x "dds " -a "+4 l1" poi(poi(poi(poi(poi(0a6d9244-4)+8)))+4) . . . 의미 없는 정보가 보일 때까지 계속 확인하는 작업도 가능하겠지만, Leak 여부를 Check 및 Leak code를 찾는 것은 모든 Thread Stack을 뒤지지 않더라고 그 전에 Hint 를 얻을 듯 하다.
|
카테고리
이글루링크
최근 등록된 덧글
그러세요
by 강세윤 at 12/15 오늘 많이 헤매다..알게 .. by youna at 12/14 글 잘 읽었습니다 . 전 .. by 위시 at 11/26 어렷다 by klhk at 11/09 dhjjgbem by kl at 11/09 17번부터 어떻게 접는지.. by tykim0131 at 10/28 ATL이나 MFC를 이용하.. by 김명신 at 09/24 복원되었군요.. 제 RSS.. by 강세윤 at 09/24 허걱, 하고 있는 것으로.. by 강세윤 at 09/15 RSS 주소 서비스는 안 .. by 정성태 at 09/15 이글루 파인더
| |||