[110] C++ 메모리 누수 확인, new/delete Memory Leak Check

[110] C++ 메모리 누수 확인, new/delete Memory Leak Check


초보자를 위한 C++ 200제 독자 포스트 : 이준우님 질문의 답변입니다.


질문 글


110번 예제 보는 중에 궁금한 게 생겼는데요?

class 안에서 변수에 메모리를 동적 할당/해제 하셨는데, 혹시 변수 메모리 할당만 하고 class 자체를 delete하면 할당된 변수의 메모리도 해제되나요??


우선 비주얼스튜디오에서 C++ 메모리 누수 확인할 방법을 소개합니다. 책에서도 소개할 걸 그랬네요. 우선 아래 코드를 봐주세요.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "stdafx.h"
#include <iostream>
#include <crtdbg.h>
 
using namespace std;
 
#ifndef _DEBUG
#define new new(_CLIENT_BLOCK,__FILE__,__LINE)
#endif
 
class TestClass{
public:
    TestClass()
    {
        data = new double[3];
        data[0= 0;
        data[1= 1;
        data[2= 2;
    }
    ~TestClass()
    {
        delete data;
    }
 
private:
    double* data;
};
 
int main()
{
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
 
    TestClass *tc = new TestClass();
    delete tc;
 
    return 0;
}
cs


3번 라인 : crtdbg.h 파일을 추가합니다.

7~9번 라인 : Debug 모드에서 수행할 #define 지시문 코드를 삽입합니다.

31번 라인 : 메모리 누수 확인할 수 있는 코드를 삽입합니다.


위 코드를 추가하면, 프로그램 종료 시 비주얼스튜디오 하단 출력창에 메모리 누수 확인 항목이 출력됩니다.


1. 이어서 질문으로 돌아가면, 결론적으로 소멸자에서 명시적으로 delete 해주지 않으면 메모리 해제가 되지 않습니다. 가령 TestClass* tc = new TestClass();라고 선언하면 tc는 객체를 가리키는 포인터로 4바이트를 갖습니다. 내부 요소는 주소를 참조하여 가리키게(->) 됩니다. 즉, 메모리 어딘가에 할당된 TestClass 객체와 tc 사이엔 포인터가 존재합니다.


그리고 포인터는 delete 하더라도 원래 가리키던 곳(TestClass 객체의 메모리 주소)을 가리킵니다. 그래서 포인터를 delete하고 NULL로 설정하면 메모리 오염도 방지할 수 있습니다.


c++ 메모리 누수 확인 new delete[C++ Memory Leak Check]


2. 메모리 구조는 포함하는 개념이 아니라 층으로 쌓여있는 개념입니다. 그래서 한 메모리 영역이 다른 메모리 영역을 포함한다기보단 참조하는 개념이죠. 그래서 한 메모리 영역을 해제했다고 해서 다른 메모리 영역까지 해제될 순 없습니다. 거꾸로 생각해보면, 내가 10001 번지를 delete했는데 컴파일러가 잘못 유추해 10002 번지를 delete 해버리면 되게 위험하겠죠.


그래서 일일이 delete 해줘야 합니다. 마찬가지로 위 코드는 에러가 발생하지 않지만, 22번 또는 34번 라인을 주석 처리하면 메모리 누수가 발생합니다. delete를 시도할 때 컴퓨터는 알아서 소멸자를 호출하는데 이때, 소멸자에 delete 코드, 그러니깐 메모리 해제 코드가 있어야 합니다.


안 그러면 아래처럼 좋지 않은 메모리 누수 확인 결과가 출력됩니다.


[110] C++ 메모리 누수 확인, newdelete Memory Leak Check[C++ Memory Leak Check]


double data 배열은 크기가 3이라 3 * 8 = 24 바이트 누수가 발생합니다. 결론은 ... 일일이 해제해야 합니다. 그러지 않고 메모리 누수 확인하면 좋지 않은 결과가 눈에 보일 겁니다. 더 궁금한 사항은 언제든 댓글로 알려주세요.



덧글1. 참고로 예제 110번 Dispose() 함수는 제가 좋아하는 이름입니다. 이것도 개취가 반영된 결과인데 C#에선 주로 메모리 해제할 때 Dispose 함수를 사용해요. 그래서 이 예제 만들 때도 Dispose라고 했네요. http://codingcoding.tistory.com/101[링크] 이 포스트는 초기화의 반대말이 무엇인지 정리된 글입니다.


덧글2. CppCheck라는 메모리 누수 확인 툴도 있습니다. 근데 비주얼스튜디오 성능이 요즘 좋아져서 크게 필요하진 않아요. http://codingcoding.tistory.com/64 [바로가기]


Release, Remove, Dispose, Clear, UnInitialize, de-Initialize, Terminate, Detonate 등 여러 가지 표현 방법이 있는데 저는 Dispose를 선택했습니다. 그냥 살다 보니 그게 익숙해서 선택한 것이죠. 가끔 이런 쓸데없는 고민해 보는 것도 재밌긴 해요.


[110] C++ 메모리 누수 확인, new/delete Memory Leak Check

이 글을 공유하기

댓글(0)

Designed by JB FACTORY