성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[tree soap] 아차! f는 기억이 나는데, m은 ㅜㅜ 감사합니다!!! ^...
[정성태] 'm'은 decimal 타입의 숫자에 붙는 접미사입니다. ...
[정성태] https://lxr.sourceforge.io/ http...
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>CoTaskMemAlloc/CoTaskMemFree과 윈도우 Heap의 관계</h1> <p> 지난 글에서 다뤘지만,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > windbg - CoTaskMemFree/FreeCoTaskMem에서 발생한 덤프 분석 사례 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/12058'>http://www.sysnet.pe.kr/2/0/12058</a> </pre> <br /> 당연히 윈도우 환경에서의 메모리 사용이니 CoTaskMemAlloc도,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > CoTaskMemAlloc function ; <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemalloc'>https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemalloc</a> </pre> <br /> 내부적으로는 Windows Heap에 의존할 수밖에 없습니다. 그럼 어떻게 의존하는지 간단하게 살펴볼까요? ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #include <iostream> #include <combaseapi.h> int main() { int size = 20; LPVOID pVoid = CoTaskMemAlloc(size); printf("pVoid == 0x%x\n", pVoid); memset(pVoid, 0xff, size); <span style='color: blue; font-weight: bold'>CoTaskMemFree</span>(pVoid); return 0; } </pre> <br /> CoTaskMemFree를 호출하는 코드를 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ...[생략]... 00835DF4 8B F4 mov esi,esp 00835DF6 8B 45 E8 mov eax,dword ptr [pVoid1] 00835DF9 50 push eax <span style='color: blue; font-weight: bold'>00835DFA FF 15 58 D1 83 00 call dword ptr [__imp__CoTaskMemFree@4 (083D158h)] </span> 00835E00 3B F4 cmp esi,esp 00835E02 E8 74 B4 FF FF call __RTC_CheckEsp (083127Bh) ...[생략]... --- onecore\com\combase\class\memapi.cxx --------------------------------------- 7623F800 8B FF mov edi,edi 7623F802 55 push ebp 7623F803 8B EC mov ebp,esp 7623F805 A1 E4 4E 39 76 mov <span style='color: blue; font-weight: bold'>eax,dword ptr [g_CMalloc (76394EE4h)]</span> // 전역 IMalloc 인스턴스를 eax에 저장 7623F80A 56 push esi // non-volatile 레지스터 값이므로 사용 전 push 7623F80B 8B 70 14 mov esi,dword ptr [eax+14h] // esi == IMalloc 인터페이스의 6번째 메서드 포인터 7623F80E 81 FE 20 F5 20 76 cmp esi,offset CRetailMalloc_Free (7620F520h) 7623F814 0F 85 C9 75 07 00 jne `Microsoft::WRL::Module<1,Microsoft::WRL::Details::DefaultModule<1> >::Create'::`2'::`dynamic atexit destructor for 'moduleSingleton''+3CC3h (762B6DE3h) 7623F81A 8B 45 08 mov eax,dword ptr [ebp + 8] // ebp + 8 == 첫 번째 인자 pVoid1 7623F81D 85 C0 test eax,eax 7623F81F 74 0F je CoTaskMemFree+30h (7623F830h) 7623F821 50 push eax 7623F822 6A 00 push 0 7623F824 FF 35 0C 50 39 76 push dword ptr [g_hHeap (7639500Ch)] <span style='color: blue; font-weight: bold'>7623F82A FF 15 94 72 39 76 call dword ptr [__imp__HeapFree@12 (76397294h)] </span> 7623F830 5E pop esi 7623F831 5D pop ebp 7623F832 C2 04 00 ret 4 </pre> <br /> 내부적으로 이미 생성해 두었던 IMalloc 전역 인스턴스(g_CMalloc)의,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > g_CMalloc {lpVtbl=<span style='color: blue; font-weight: bold'>0x7616d158</span> {combase.dll!IMallocVtbl CRetailMallocVtbl} {QueryInterface=0x76315f80 {combase.dll!CMalloc_QueryInterface(IMalloc *, const _GUID &, void * *)} ...} } CMalloc </pre> <br /> 6번째 메서드가,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>0x7616D158</span> 76315f80 (QueryInterface) 0x7616D15C 7628e8a0 (AddRef) 0x7616D160 7628e8a0 (Release) 0x7616D164 7620f260 (IMalloc::Alloc) 0x7616D168 762781b0 (IMalloc::DidAlloc) <span style='color: blue; font-weight: bold'>0x7616D16C 7620f520 (IMalloc::Free) <== eax + 14h </span> 0x7616D170 7626e3a0 0x7616D174 76290f30 0x7616D178 76315fc0 0x7616D17C 00000000 0x7616D180 00000001 </pre> <br /> CRetailMalloc_Free 함수와 동일한 주소인지 체크한 후 맞는다면, HeapFree를 다음과 같은 인자로 호출합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > HeapFree(g_hHeap, 0, pVoid); </pre> <br /> 여기서 g_hHeap은 Win32 프로세스가 생성하는 default Heap으로 Win32 API로는 <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-getprocessheap'>GetProcessHeap</a>으로 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > HANDLE hDefaultHeap = GetProcessHeap(); printf("pVoid == 0x%x\n", hDefaultHeap); </pre> <br /> 이게 끝입니다. 이후부터는 HeapFree의 절차를 그대로 따릅니다. 따라서 실질적인 기준으로 본다면, g_CMalloc 관련 코드도 단순히 CRetailMalloc_Free와 비교하는 것일 뿐 정작 g_CMalloc::Free 메서드를 호출하는 것도 아니기 때문에 CoTaskMemFree는 곧바로 HeapFree를 호출하는 것과 별반 다르지 않습니다.<br /> <br /> 정리하면, CoTaskMemAlloc == HeapAlloc(g_hHeap, ...)으로, CoTaskMemFree == HeapFree(g_hHeap, ...)이라고 보면 됩니다.<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
2069
(왼쪽의 숫자를 입력해야 합니다.)