성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 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...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
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'>gflags와 _CrtIsMemoryBlock을 이용한 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 분석 사례 - ODP.NET 사용 시 Finalizer에서 System.AccessViolationException 예외 발생으로 인한 비정상 종료 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11785'>http://www.sysnet.pe.kr/2/0/11785</a> 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 /> CoTaskMemFree에서 발생한 예외의 원인이 Heap이 깨진 것이라고 설명했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ntdll!RtlReportCriticalFailure+97 ntdll!RtlpHeapHandleError+12 ntdll!RtlpLogHeapFailure+96 ntdll!RtlFreeHeap+823 OraOps19!ssmem_free+f OraOps19!OpsMetFreeValCtx+89 DomainNeutralILStubClass.IL_STUB_PInvoke(Oracle.DataAccess.Client.OpoMetValCtx*)+6e Oracle.DataAccess.Client.MetaData.Finalize()+25 </pre> <br /> 결국 해결을 하긴 했지만,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > windbg - Marshal.FreeHGlobal에서 발생한 덤프 분석 사례 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/12086'>http://www.sysnet.pe.kr/2/0/12086</a> </pre> <br /> 그래도 혹시나 이 문제가 제가 만든 응용 프로그램에서 발생했다고 가정하고 문제를 빠르게 찾을 수 있는 방법이 없을까 고민을 하게 되었는데요. 가령 지난 글에서 사용한 예제 코드의 경우,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > AcLayers의 API 후킹과 FaultTolerantHeap ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/12050'>http://www.sysnet.pe.kr/2/0/12050</a> </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > char *cp = new char[10]; (*(cp - 5))++; </pre> <br /> CRT Heap의 헤더를 깨먹은 것이기 때문에 "delete cp;"를 수행 시 비정상 종료할 수 있습니다. C++의 경우에는 대개 할당을 한 함수 내에서 해제도 함께 하는 경우가 많기 때문에 문제를 쉽게 발견할 수 있는데, 반면 C#처럼 Finalizer로 인해 해제되는 경우에는 원인 분석이 쉽지 않습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이런 유의 원인 분석을 위해 도움이 되는 것이 있다면 gflags의 heap 관련 옵션을 켜는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Detecting Heap Corruption Using GFlags and Dumps ; <a target='tab' href='https://blogs.msdn.microsoft.com/webdav_101/2010/06/22/detecting-heap-corruption-using-gflags-and-dumps/'>https://blogs.msdn.microsoft.com/webdav_101/2010/06/22/detecting-heap-corruption-using-gflags-and-dumps/</a> Debugging Heap corruption with Application Verifier and Debugdiag ; <a target='tab' href='https://blogs.msdn.microsoft.com/lagdas/2008/06/24/debugging-heap-corruption-with-application-verifier-and-debugdiag/'>https://blogs.msdn.microsoft.com/lagdas/2008/06/24/debugging-heap-corruption-with-application-verifier-and-debugdiag/</a> </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > gflags.exe -p /enable w3wp.exe /full gflags.exe -p /enable ConsoleApplication1.exe /full </pre> <br /> 그러고 보니 예전에 ^^ 0xBAADF00D 쿠키를 확인하기 위해 사용해 본 적이 있었는데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Win32 Debug CRT Heap Internals의 0xBAADF00D 표시 재현 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11255'>http://www.sysnet.pe.kr/2/0/11255</a> </pre> <br /> 옵션에 따라 할당 시점의 call stack을 가지고 있기 때문에 free/delete를 수행한 시점에 예외가 발생해도 어떤 메모리를 위해 할당한 것인지 구분할 수 있어 그와 연관된 코드를 좀 더 세심하게 찾아보는데 도움은 될 수 있습니다.<br /> <br /> 하지만, 저런 식으로 하면 Heap 관련 부가 정보가 더 점유하기 때문에 이전에는 CRT Header를 깨먹은 것도 gflags 이후에는 header가 아닐 수 있어 오히려 문제가 감춰지는 경우도 있습니다. (실제로 위의 예제 코드가 그런 경우입니다.) 이런저런 이유로 인해 이런 유의 문제를 해결하는 정답은 없습니다. 운이 좋다면, 깨진 header에 저장된 데이터를 보고... 만약 그것이 "파일 경로"인 듯한 데이터가 들어 있다면 프로그램에서 관련 데이터를 썼을 것 같은 코드를 범인으로 유추해 나가는 정도가 됩니다.<br /> <br /> 부가적으로 (Windows Heap이 아닌) CRT heap의 경우 _CrtIsMemoryBlock이라는 디버그 빌드에서만 사용 가능한 함수가 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > _CrtIsMemoryBlock ; <a target='tab' href='https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/reference/crtismemoryblock?view=vs-2019'>https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/reference/crtismemoryblock?view=vs-2019</a> </pre> <br /> 그래도 이게 그나마 쓸만한데요, 다음과 같이 사용하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > long requestNumber; char* filename[MAX_PATH]; int linenumber; printf("_CrtIsMemoryBlock == %d\n", _CrtIsMemoryBlock(<span style='color: blue; font-weight: bold'>cp</span>, sizeof(char) * 10, &requestNumber, filename, &linenumber)); </pre> <br /> "(*(cp - 5))++;"로 깨진 바로 저 포인터를 넘겨서 해당 메모리가 유효한 CRT Heap의 구조를 가지고 있는지 체크해 줍니다. 물론, 그렇다고 해서 Header를 깬 위치를 알 수 있는 것은 아니고 의심이 가는 부분에 디버깅 용으로 저 코드를 심어놓고 assert 등의 처리를 해야 합니다.<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1827
(왼쪽의 숫자를 입력해야 합니다.)