조회 수 40468 댓글 2
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print
작성자 : 김문규
최초 작성일 : 2009. 3.25

1. 들어가며
메모리 누수를 탐지는 방법은 매우 많습니다. 하지만, 실은 잘 모르는 경우가 많습니다. 매크로를 이용하시는 분도 있고, 툴을 사용하시는 분도 있고.... 다양한 방법이 있지만 이번 포스트에서는 _CrtDumpMemoryLeaks()라는 함수를 이용해서 간단하게 누수 지점을 탐지하는 법을 소개하겠습니다.

2. 문제의 코드
int main()
{
 char* pA = new char[20];
 return 0;
}

메모리를 할당하였지만, 이를 해제하고 있지 않습니다. (물론 해당 예제에서는 어플리케이션이 종료되기 때문에 상관없지만 할당 후 해제 하지 않았다는 점에 주목하세요.)

이렇게 간단한 코드이라면 상관없겠지만, 1000 라인 정도에 new만 50개 정도하는 모듈이라고 가정하면 delete[]를 빼먹는 것은 흔하게 있는 실수일 지도 모릅니다.

3. 탐지하기
#include <crtdbg.h>
int main()
{
 char* pA = new char[20];
 _CrtDumpMemoryLeaks();
 
return 0;
}

적색으로 표시된 2개의 코드를 삽입했습니다. 결과창은 다음과 같습니다.

메모리 누수가 발견되었다고 알려주네요. 그런데, 어딘지 잘 알 수없는 암호문 같네요.
하지만, 여기서 주목할 점은 {56} 입니다. {56}이라는 메모리 참조값을 가지는 지점이 해제되지 않았다는 뜻입니다.
그럼 {56}이 어떤 지점인지 찾으면 되겠네요~
그래서, 코드를 아래처럼 수정합니다.

#include <crtdbg.h>
int main()
{
 _CrtSetBreakAlloc(56);
 char* pA = new char[20];
 _CrtDumpMemoryLeaks();
 return 0;
}

그러면, {56} 메모리 지점을 생성하려고 할 때, 비줠스튜디오가 break할 것인지를 물어봅니다. 여기서, SHIFT+F11 신공으로 몇번만 함수를 빠져나오면 우리 코드 레벨에서 어떤 지점이 문제인지 알 수 있게 됩니다.


참 쉽죠잉~

4. 주의할 점
_CrtDumpMemoryLeaks() 이 함수는 호출되는 시점을 기준으로 해제되지 않은 메모리 영역을 알려주게 됩니다. 즉 정상적으로 delete 함수를 호출하는 코드라고 하더라도 CrtDumpMemoryLeaks()가 delete 함수보다 먼저 호출된다면, 메모리 누수로 감지하게 됩니다. 따라서, 함수의 위치에 따라서 지혜롭게 개발자가 잘 판단해야 합니다. 특히 전역변수의 경우를 잘 판단하셔야 겠지요.

5. 마치면서
메모리 누수는 꼭 피해야 하는 경우이며, 이를 위한 기술을 많이 가지고 있으면 좋습니다. 이 중에 가장 간편한 방법이 아닐까 합니다. 주의할 점만 확실히 이해하셨다면 매우 간편하지만 강력한 탐지법이 될 것입니다.
  • Dreamy 2010.11.02 09:43

    Memory Leak은 발생합니다.
    list안에 들어간 정수들을 할당받았고 삭제를 해주지 않기에 발생합니다.
    하지만 Leak이 발생한 것을 확인하고자 한다면 Memory 상태에 관하여 출력을 하여 주어야 보실 수 있습니다.
    Debug 메시지를 보는 프로그램 같은 것으로 확인하신다면 프로그램 종료시에 발생한 메모리 누수를 볼 수도 있습니다.
    아니면 표준 출력으로 전환하여 확인 할 수도 있습니다.


        // Send all reports to STDOUT
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );


    이처럼 표준 출력으로 메시지를 출력하도록 하여 주시고


    _CrtDumpMemoryLeaks(); 함수를 사용하시면 메모리 누수를 확인하실 수 있습니다.
    또한 현재 메모리 상태를 확인 하실려면
      _CrtMemState st;
      _CrtMemCheckpoint(&st);
      _CrtMemDumpStatistics(&st); 와 같이 하셔서 확인이 가능합니다.

  • Dreamy 2010.11.02 15:24

    이거에 대한 MSDN 내용

    ===================================

    메모리 누수를 탐지하는 데 사용하는 기본 도구는 디버거와 CRT 디버그 힙 함수입니다. 디버그 힙 함수를 사용하려면 다음 문이 프로그램에 포함되어 있어야 합니다.

    #define CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>
    참고   #include 문은 위의 순서를 따라야 합니다. 순서를 변경하면 함수를 사용해도 제대로 작동하지 않습니다.

    crtdbg.h를 포함하여, 메모리 할당과 할당 취소를 추적하는 해당 디버그 버전, _malloc_dbg_free_dbgmallocfree 함수를 매핑합니다. 이 매핑은 _DEBUG가 정의된 디버그 빌드에서만 발생합니다. 릴리스 빌드에서는 일반적인 malloc 함수와 free 함수가 사용됩니다.

    #define 문은 CRT 힙 함수의 기본 버전을 해당 디버그 버전에 매핑합니다. 이 문을 반드시 사용할 필요는 없지만 사용하지 않으면 메모리 누수 덤프에 별로 유용하지 않은 정보가 포함될 수 있습니다.

    위에서 설명한 문을 추가한 후 프로그램에 다음 문을 포함하여 메모리 누수 정보를 덤프할 수 있습니다.

    _CrtDumpMemoryLeaks();

    디버거에서 프로그램을 실행하면 _CrtDumpMemoryLeaks출력 창에 메모리 누수 정보를 표시합니다. 메모리 누수 정보가 다음과 같이 표시됩니다.

    Detected memory leaks!
    Dumping objects ->
    C:\PROGRAM FILES\VISUAL STUDIO\MyProjects\leaktest\leaktest.cpp(20) : {18} 
    normal block at 0x00780E80, 64 bytes long.
     Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
    Object dump complete.

    #define _CRTDBG_MAP_ALLOC 문을 사용하지 않으면 메모리 누수 덤프가 다음과 같이 표시됩니다.

    Detected memory leaks!
    Dumping objects ->
    {18} normal block at 0x00780E80, 64 bytes long.
     Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
    Object dump complete.

    _CRTDBG_MAP_ALLOC가 정의되지 않으면 다음 사항이 표시됩니다.

    • 메모리 할당 번호(중괄호 안에 표시)
    • 블록 형식(표준, 클라이언트 또는 CRT)
    • 16진수로 표기한 메모리 위치
    • 바이트로 표기한 블록 크기
    • 16진수로 표기한 처음 16바이트의 내용

    _CRTDBG_MAP_ALLOC가 정의되면 누수된 메모리가 할당된 파일을 찾을 수 있습니다. 파일 이름 뒤에 오는 괄호 안의 숫자(예: 20)는 파일에서의 줄 번호입니다.

    메모리가 할당된 소스 파일의 줄로 이동하려면

    • 출력 창에서 파일 이름과 줄 번호가 있는 줄을 두 번 클릭합니다.

      - 또는 -

    • 출력 창에서 파일 이름과 줄 번호가 있는 줄을 선택하고 F4 키를 누릅니다.

    _CrtSetDbgFlag

    프로그램이 항상 같은 위치에서 종료되는 경우에는 _CrtDumpMemoryLeaks를 쉽게 호출할 수 있습니다. 그러나 프로그램이 여러 위치에서 종료되는 경우를 생각해 보십시오. 종료할 수 있는 모든 위치에서 _CrtDumpMemoryLeaks를 호출하는 대신 프로그램 시작 부분에 다음 호출을 포함할 수 있습니다.

    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

    이 문은 프로그램이 종료될 때 자동으로 _CrtDumpMemoryLeaks를 호출합니다. 위의 예제와 같이 비트 필드 _CRTDBG_ALLOC_MEM_DF_CRTDBG_LEAK_CHECK_DF를 모두 설정해야 합니다.

    CRT 보고서 모드 설정

    기본적으로 _CrtDumpMemoryLeaks는 위에서 설명한 대로 출력 창의 디버그 창으로 메모리 누수 정보를 덤프합니다. _CrtSetReportMode를 사용해 다른 위치로 덤프하도록 다시 설정할 수 있습니다. 라이브러리를 사용할 경우 출력을 다른 위치로 다시 설정할 수 있습니다. 이 경우 다음 문을 사용하여 출력 위치를 출력 창으로 다시 설정할 수 있습니다.

    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );

    _CrtSetReportMode를 사용하여 출력을 다른 위치로 보내는 방법은 _CrtSetReportMode를 참조하십시오.


나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소

Designed by sketchbooks.co.kr / sketchbook5 board skin

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5