본문 바로가기

Library/Windows Programming

Memory Leak Check

Visual C++에서는 MFC나 C 런타임 라이브러리 내에서 메모리 누수를 검사할 수 있는 간단한 방법을 제공한다. MFC는 사용자가 특별히 작업해주지 않아도 메모리 누수를 보고해주는 기능이 포함되어 있는 반면, MFC를 사용하지 않는 프로그램들은 메모리 누수를 검사하도록 사용자가 직접 코드를 추가해주어야 한다.


간단히 절차를 말하면, 다음과 같다.

전처리 부분의 가장 위쪽, 보통 PCH 다음에 #define _CRTDBG_MAP_ALLOC를 선언하고, #include "crtdbg.h"를 포함한다.

#include "stdafx.h"
#define _CRTDBG_MAP_ALLOC
#include "crtdbg.h"

그리고, 필요한 함수는 _CrtSetDbgFlag(), _CrtDumpMemoryLeaks(), _CrtSetReportMode() 세가지이다. 먼저, _CrtSetDbgFlag()를 사용하여 기본적인 디버그 설정을 한 다음, 메모리 누수를 검사할 덤프 시점에 _CrtDumpMemoryLeaks()를 호출하는 방식이다. 콘솔 프로그램을 작성한다면, 보통 main() 함수에서 return 이전 시점이 될 것이다.

여기서, 프로그램이 종료되는 위치를 고정적으로 선택할 수 없다면, _CrtDumpMemoryLeaks()를 종료되는 부분에 모두 작성하는 대신, _CrtSetDbgFlag() 함수를 사용할 수 있다. 이 함수의 파라미터 설정에 따라 어느 시점에서 메모리 누수를 검사할 수 있는지 설정하는 것이 가능하다. 예를 들어서, C++의 소멸자를 사용한 메모리 해제는 일반적인 경우라면 메모리 누수라고 보고될 것이다. 즉, 스마트 포인터와 같은 것을 작성하는 도중이라면, 소멸자의 행동까지 추적하지 않기 때문에 메모리 누수라고 보고될 것이다. 이 경우, _CrtSetDbgFlag()의 파라미터를 적절히 설정하는 것으로 메모리 누수 검사 시점을 선택할 수 있다.

_CrtSetReportMode()는 사용해도 그만이고, 사용하지 않아도 그만이다. 중요한 것은 _CrtSetDbgFlag()와 _CrtDumpMemoryLeaks()이다.

예를 든다면, 다음과 같다.

#define _CRTDBG_MAP_ALLOC
#include "crtdbg.h"

int main()
{
    int DbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
    DbgFlag |= _CRTDBG_LEAK_CHECK_DF;
    _CrtSetDbgFlag(DbgFlag);

    char* pMem = new char(64);

    _CrtDumpMemoryLeaks();
    return 0;
}

여기서, _CrtDumpMemoryLeaks()를 프로그램의 종료 시점에서 호출하고 싶다면, DbgFlag에 _CRTDBG_ALLOC_MEM_DF 플래그를 추가로 설정해주어야 한다. 즉, 위의 코드와 같은 경우, _CrtDumpMemoryLeaks() 다음에 힙을 정상적으로 해제하는 코드가 있더라도 메모리 누수를 보고하게 된다. _CRTDBG_ALLOC_MEM_DF 플래그를 설정하면, _CrtDumpMemoryLeaks()를 호출하지 않더라도 Output 윈도우에 메모리 누수 여부를 알려줄 것이다.


MSDN Document : http://support.microsoft.com/kb/601929/ko,
http://msdn.microsoft.com/en-us/library/5at7yxcs(VS.71).aspx