이이프
IeF 제멋대로 세상
이이프
전체 방문자
오늘
어제

공지사항

  • ✔ Info
  • 전체 글보기 (56)
    • 💻프로그래밍 내용 정리 (55)
      • C (0)
      • C++17 (55)
    • 💻게임메이커 (0)
    • 💻언리얼엔진 (0)
    • 💻유니티 (0)
    • 🎈[팀&자작]게임소개 (0)
    • 📃게임제작기술 (0)
    • 🎨그림놀이 (0)
    • 📒대학생활 (0)
    • 😃잡담 (1)
    • 🕹게임성과 (0)
    • 💷자격증 (0)

블로그 메뉴

  • 방명록

최근 글

최근 댓글

티스토리

hELLO · Designed By 정상우.
이이프

IeF 제멋대로 세상

[C++ 7.5.1] 메모리 누수, 비주얼 C++을 이용한 메모리 누수 탐지 및 수정 방법
💻프로그래밍 내용 정리/C++17

[C++ 7.5.1] 메모리 누수, 비주얼 C++을 이용한 메모리 누수 탐지 및 수정 방법

2022. 10. 3. 10:24
728x90

1. 메모리 누수

메모리 누수 문제는 C/C++ 프로그래밍 과정에서 발견하거나 해결하기 가장 힘든 작업이다.

원하는 결과를 내도록 프로그램이 실행될수록 메모리 공간을 잡아먹는다면 메모리 누수 현상이 발생한 것이다.

 

메모리 누수 현상은 할당했던 메모리를 제대로 해제하지 않을 때 발생한다.

new에 대응되는 delete를 빠짐없이 작성하더라도 누수 현상이 발생하는 경우가 있다.

 

다음 Simple 클래스 코드를 보면 할당한 메모리를 적절히 해제하도록 작성했다.

class Simple
{
private:
    int* mIntPtr;
public:
    Simple() { mIntPtr = new int(); }
    ~Simple() { delete mIntPtr; }
    void setValue(int value) { *mIntPtr = value; }
};

void doSomething(Simple*& outSimplePtr)
{
    outSimplePtr = new Simple(); // 버그! 원본 객체를 삭제하지 않았다.
}

int main()
{
    Simple* simplePtr = new Simple(); // Simple 객체 하나를 할당한다.
    doSomething(simplePtr);
    delete simplePtr; // 두 번째 객체만 해제한다.
    return 0;
}

그런데 doSomething()을 보면 outSimplePtr 포인터가 다른 Simple 객체를 가리키도록 변경했는데,

이때 기본에 가리키던 객체를 삭제하지 않아서 메모리 누수가 발생했다.

객체를 가리키고 있던 포인터를 놓치면 그 객체를 삭제할 방법이 없다.

 

 


 

2. 비주얼 C++을 이용한 메모리 누수 탐지 및 수정 방법

마이크로소프트 비주얼 C++을 사용하고 있다면 디버그 라이브러리에서 기본으로 제공하는

메모리 누수 감지 기능을 활용할 수 있다.

 

기본 설정에 따르면 이 기능을 사용하지 않게 돼 있지만 MFC 프로젝트를 생성할 때는 자동으로 활성화 된다.

MFC가 아닌 다른 프로젝트에서 이 기능을 사용하려면 코드의 첫머리에 다음 세 문장을 추가한다.

#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>

반드시 이 순서대로 작성해야 한다. 또한 new 연산자를 다음과 같이 새로 정의한다.

#ifdef _DEBUG
    #ifndef DBG_NEW
        #define DBG_NEW new (_NORMAL_BLOCK , __FILE__ , __LINE__ )
        #define new DBG_NEW
    #endif
#endif // _DEBUG

이때 new 연산자를 #ifndef DBG_NEW 구문 안에 정의했다.

따라서 애플리케이션을 디버그 모드로 컴파일해야 새로 정의한 new가 적용된다.

 

마지막으로 main() 함수의 첫 부분에 다음 문장을 작성한다.

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

그러면 애플리케이션이 종료할 때 비주얼 C++의 CRT 라이브러리는

현재 감지된 모든 메모리 누수 현상을 디버그 콘솔에 출력한다.

 

이렇게 설정한 상태에서 앞에서 본 메모리 누수 현상이 발생하는 코드를 실행하면

디버그 콘솔에 다음과 같은 메시지가 출력된다.

이 결과를 보면 메모리가 할당됐지만 해제되지 않은 부분이 어느 파일의 어느 줄에 있는지 확실히 알 수 있다.

줄 번호는 파일 이름 뒤에 소괄호로 묶여 있다.

 

중괄호로 묶인 숫자는 메모리 할당 횟수다.

예를 들어 {74}는 현재 프로그램이 구동한 후 74번째 할당했다는 것을 의미한다.

 

VC++에서 제공하는 _CrtSetBreakAlloc() 함수를 호출하면 메모리가 할당되는 순간 실행을 중단하고

디버거를 구동하도록 VC__ 디버그 런타일을 설정할 수 있다.

main() 함수의 시작 부분에 다음 문장을 작성하면 메모리를 74번째 할당하는 시점에 디버거를 구동한다.

_CrtSetBreakAlloc(74);

앞에서 본 Simple 클래스 예제에서 메모리 누수 현상이 발생하는 지점은 두 군데다.

하나는 Simple 객체를 삭제하지 않은 30번 줄이고, 다른 하나는 이 객체가 정수를 힙에 할당하는 15번 줄이다.

비주얼 C++ 디버거의 출력 윈도우에서 메모리 누수 현상을 가리키는 항목을 더블 클릭하면 해당 코드로 이동한다.

'💻프로그래밍 내용 정리 > C++17' 카테고리의 다른 글

[C++ 8.2.2-1] 메서드 정의 방법  (0) 2022.10.03
[C++ 8.2.1] 클래스 정의  (0) 2022.10.03
[C++ 7.4.3] weak_ptr  (0) 2022.10.03
[C++ 7.4.2] shared_ptr  (0) 2022.09.25
[C++ 7.4.1] unique_ptr  (0) 2022.09.25
    '💻프로그래밍 내용 정리/C++17' 카테고리의 다른 글
    • [C++ 8.2.2-1] 메서드 정의 방법
    • [C++ 8.2.1] 클래스 정의
    • [C++ 7.4.3] weak_ptr
    • [C++ 7.4.2] shared_ptr
    이이프
    이이프
    게임 프로그래머 지망생 / Since 2022.08.14

    티스토리툴바