Skip to content

[C/C++] 스마트 포인터(Smart Pointer) #1

@miusic

Description

@miusic

스마트 포인터?

자바는 garbage collector를 사용하지만, c++은 사용자가 스스로 메모리 할당/해제를 하면서 관리해 주어야 한다.

할당받은 메모리를 해제하지 않으면 프로그램은 해당 메모리를 계속 사용하고 있는 것으로 인지하고, 메모리 누수(memory leak)이 발생하게 된다. (프로그램이 종료되면 OS에 의해 해제)


예시

코드 블록
#include <iostream>

using namespace std;

class Resource
{
  int *data;

public:
  Resource()
  {
    data = new int[100];
    cout << "리소스 획득\n";
  }

  ~Resource()
  {
    cout << "소멸자 호출\n";
    delete[] data;
  }
};

void foo() { Resource *pRes = new Resource(); }

int main()
{
  foo();

  return 0;
}

위 코드를 실행하면 결과는 다음과 같다.

리소스 획득

main에서 foo()함수를 호출했지만, 소멸자는 호출되지 않고 메모리가 해제되지 않은 상태로 남아있다.

delete를 foo()함수 안에서 해주지 않으면, 생성된 객체를 가리키던 pRes는 메모리에서 사라지지만, 힙 메모리 어딘가에 Resource 클래스 객체가 남아있어 메모리 누수가 발생하게 된다.

그럼 다음과 같이 간단하게 delete만 넣어주면 해결이 될까?

void foo()
{
  Resource *pRes = new Resource();

  // do something

  delete pRes;
}

위 예시는 간단한 함수이기 때문에 문제가 없지만, 프로그램이 커지고 복잡해질 수록 메모리 해제에 실패하는 경우를 놓치기 쉽다.

// do something의 어딘가에서 함수가 return 될 수도 있고, delete가 어떤 루프 안에 있는데 continue / break 등에 의해 루프를 빠져나오는 경우도 있을 수 있다.

아래의 경우는 예외가 발생해서 delete를 놓치는 경우다.

코드 블록
#include <iostream>

using namespace std;

class Resource
{
  int *data;

public:
  Resource()
  {
    data = new int[100];
    cout << "리소스 획득\n";
  }

  ~Resource()
  {
    cout << "소멸자 호출\n";
    delete[] data;
  }
};

void thrower() { throw 1; }

void foo()
{
  Resource *pRes = new Resource();
  thrower();

  delete pRes;
}

int main()
{
  try
  {
    foo();
  }
  catch (int i)
  {
    cout << "예외 발생\n";
  }

  return 0;
}

이러한 메모리 누수를 방지하기 위해 c++ 11 부터 스마트 포인터(Smart pointer)가 도입되었다.

스마트 포인터는 포인터 객체를 통해서 문제를 해결한다.

일반적인 포인터가 아니라, 포인터 객체를 만들어 줌으로써 리소스의 사용이 끝나면 소멸자를 호출하여 자동으로 delete를 불러주도록 설계되어 있다.

이러한 디자인 패턴은 RAII (Resource Acquisition Is Initialization) : 리소스의 획득은 초기화이다라는 용어로 불린다.

즉, 리소스 관리를 할당한 객체를 통해서 수행한다는 의미로, 리소스를 획득하고 나면 곧바로 객체에 리소스 관리를 넘겨준다는 것을 의미한다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions