티스토리 뷰

C++을 사용할때 가장 실수하기 쉬운 부분이 바로 memory leak 이다. memory leak 은 즉시 알아채기 어렵고 메모리가 부족하다는 것을 깨달아도 어떤 코드에서 memory leak 이 발생하는지 찾기가 쉽지 않다. 미리 예방하는 것이 최선이며 이때 알아야할 가장 중요한 부분이 바로 소멸조건이다. 이 소멸조건은 포인터를 사용하는 변수와 포인터를 사용하지 않는 변수가 다르다는 것을 주의해야한다. 해당 포스트에서는 지역변수와 멤버변수를 위주로 다루도록 하겠다.

 

일반 변수

먼저 포인터를 사용하지 않고 선언한 일반 변수의 소멸조건을 알아보도록 하겠다. 소멸조건은 다음과 같다.

 

  1. 블록을 벗어나는 경우
  2. 새로 변수를 할당하는 경우

두번째 조건은 아주 쉽다. 

MyClass myClass;
MyClass newClass;
myClass = newClass; // 1번째 줄에서 생성된 객체의 소멸자 호출

이미 선언된 객체에 새로운 객체를 할당하는 경우 기존에 선언된 객체는 소멸된다.

 

첫번째 조건에서 말하는 블록은 중괄호쌍을 의미한다. 대표적으로 함수가 블록 영역에 속한다.

void foo() {
    MyClass myClass;
    return;  // myClass 객체 소멸
}

 블록 안에서 생성된 객체는 블록을 벗어나는 순간 소멸된다.

포인터 변수

앞서 본 일반 변수의 소멸조건과는 다르게 동적할당된 포인터 변수는 블록을 벗어나더라도 메모리가 해제되지 않는다. 

void foo() {
    MyClass *myClass = new MyClass();
    return; // 함수가 종료되어도 myClass의 소멸자는 호출되지 않는다.
}

위와 같이 구현을 하는 경우 myClass 객체는 소멸되지 않고 메모리를 차지한다. 즉 memory leak 이 발생하는 것이다. 이 문제는 강제로 소멸시켜주어 간단히 해결할 수 있다. 바로 delete를 사용해서 말이다. delete를 사용하게 되면 myClass 객체는 소멸자를 호출하고 메모리를 해제시킨다. 

 

그렇다면 class의 멤버변수가 포인터로 선언된 경우에는 어떻게 될까?

 

포인터를 사용하지 않는 멤버 변수의 경우에는 객체가 소멸됨과 동시에 멤버 변수 또한 함께 소멸된다. 그러나 포인터 멤버 변수의 경우에는 위와 마찬가지로 소멸되지 않는다. 그 이유는 무엇일까?

 

고찰

이 내용은 저의 개인적인 생각이 들어있음을 미리 알립니다.

 우리가 잘 알고 있는 call by reference call by value 를 생각해보자. 전자에 경우에는 메모리 주소 값을 공유하게 된다. 즉, 두 개의 서로 다른 변수가 같은 메모리를 참고하게 되는 것이다. 그런데 일반적인 변수처럼 함수가 끝났을때 메모리를 해제해버리게 된다고 생각해보자. 함수 파라미터는 소멸되어도 문제가 없지만 함수를 호출한 쪽에서는 존재하지 않는 메모리를 가르키게 된다. 큰 프로젝트에서 위와 같은 경우가 발생해버린다면 원인을 찾기가 쉽지 않을 것이다. 하지만 후자의 경우에는 문제가 없다. 왜냐하면 파라미터와 아규먼트가 서로 다른 메모리를 참조하기 때문이다. 위와 같은 이유로 포인터 변수가 해제되지 않는다고 생각한다.

 

해결방법

 C++11이 되면서부터 위와 같은 문제를 간단히 해결할 수 있다. 바로 스마트 포인터를 이용하는 것이다. 스마트 포인터는 Java와 같이 메모리를 자동으로 해제해준다. 

'C++' 카테고리의 다른 글

[C++] call by reference  (0) 2019.07.05
[C++] struct와 class  (0) 2019.06.26
[C++] move 함수 이해하기 - 기초  (0) 2019.06.24
[C++] namespace 란 무엇인가?  (0) 2019.04.21
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함