핸들 누수 지점 찾아내기

  • Post author:
  • Post category:
  • Post comments:0 Comments
  • Post last modified:February 8, 2020

핸들 누수 파악하자

작업 관리자나 Process Explorer에는 열(Column)을 확장하는 옵션이 있다. 보통 메모리, 가상 메모리, 핸들, 스레드 정도를 추가하고, 경우에 따라 GDI 개체 수 같은 항목도 선택한다. 프로그램 시작할 때의 핸들 수와 나중의 핸들 수가 상당히 차이 난다면 핸들 누수가 있다고 보면 된다.

어느 핸들이 문제인가?

Process Explorer를 연다. [View/Show Lower Pane] 옵션을 선택한다. 이제 [View/Lower Pane View/Handles]를 선택하면 프로세스가 열어놓은 핸들 목록이 아래 쪽 화면에 표시된다. 기본적으로 핸들의 타입과 이름, 그리고 값 정도를 보여주는데, [View/Select Columns/Handle]에 들어가면 Access Mask나 Object Address 옵션이 있다. 이 두 옵션은 선택해두자. 마지막으로 [View/Show Unnamed Handles and Mappings]를 고르면 이름 없는 핸들까지 모두 보인다. 프로그래밍하다 보면 핸들 이름을 정해주지 않는 일이 잦기 때문에 반드시 이 옵션을 선택하자.

Process Explorer

Process Explorer

정확한 문제 지점을 찾아내자

문제 지점을 알아내는 방법은 많지만, 여기선 Application Verifier를 쓰겠다. Application Verifier를 실행시키고, [File/Add Application]에서 디버깅하고자 하는 대상 애플리케이션을 선택한다. 오른쪽 화면에서 [Basics/Handles]만 선택한 후, Save 버튼을 누른다.

Application Verifier

Applicatoin Verifier

WinDbg를 실행시키고 대상 애플리케이션을 열거나(File/Open Executable)나 대상 애플리케이션에 연결한다(File/Attatch a Process). Application Verifier에 대상 애플리케이션을 등록해놓았기 때문에, 실행시키자마자 애플리케이션은 중지(Break)된다. 이제 [Debug/Go] 또는 F5를 눌러서 원하는만큼 애플리케이션을 실행시킨다. 충분하다고 생각될 때 다시 [Debug/Break]를 누른다. 이제 트레이스할 일만 남았다.

0:013>.sympath
Symbol search path is: SRV*http://msdl.microsoft.com/download/symbols
0:014> !htrace
--------------------------------------
Handle = 0x00000048 - CLOSE
Thread ID = 0x00000a40, Process ID = 0x00000aa4

0x7c809b8b: kernel32!CloseHandle+0x00000051
0x003a4df9: vfbasics!AVrfpCloseHandle+0x00000089
0x00584fe2: DEBUG_TestClient!FClientxxxx::~FClientxxxx::~+0x00000092
0x00562b00: DEBUG_TestClient!FClient----::~FClient+0x00000100
0x0056295b: DEBUG_TestClient!FClient****::`scalar deleting destructor'+0x0000002b
0x00562728: DEBUG_TestClient!FClient####::Delete+0x00000138
--------------------------------------

이제 트레이스 결과를 보고 디버깅하면 된다.

주의

  • 실제로 트레이스를 해보면 로그가 엄청나게 길어서 WinDbg 화면에 다 표시되지 않는다. 이런 경우엔 !htrace를 하기 전에 [Edit – Open/Close Log File]에서 로그 파일을 지정해주면 된다.

  • 트레이스가 끝났으면 Application Verifier에 등록해 대상 애플리케이션을 삭제해야 한다. 그렇지 않으면 매번 실행시킬 때마다 중지(Break)된다. 디버거에 연결해주기 전까지 그 상태로 있으니 곤란하다.

    혹시나 그래도 문제가 해결되지 않으면 레지스트리 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\Current Version\Image File Execution Options\대상 애플리케이션]을 지우면 된다.

참고 문헌

Author Details
Kubernetes, DevSecOps, AWS, 클라우드 보안, 클라우드 비용관리, SaaS 의 활용과 내재화 등 소프트웨어 개발 전반에 도움이 필요하다면 도움을 요청하세요. 지인이라면 가볍게 도와드리겠습니다. 전문적인 도움이 필요하다면 저의 현업에 방해가 되지 않는 선에서 협의가능합니다.
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments