Post List

2015년 1월 4일 일요일

자원 관리에는 객체가 그만!

* 자원 누출을 막기 위해, 생성자 안에서 자원을 획득하고 소멸자에서 그것을 해제하는 RAII (Resource Acquisition Is Initialization) 객체를 사용합시다.

void f() {
    Invest *pInv = new Invest();
    ...
    delete pInv;
}

 위의 Code에서 ... 부분에서 return이 되거나, 예외가 발생해버리면 pInv가 삭제되지 않을 수가 있다. 자원을 항상 해제되도록 만들 방법은, 자원을 객체에 넣고 그 자원 해제를 소멸자가 맡도록 하는 것입니다.

* 일반적으로 널리 쓰이는 RAII Class는 tr1::shared_ptr 그리고 auto_ptr입니다. 이 둘 가운데 tr1::shared_ptr이 복사 시에 동작이 직관적이기 때문에 대개 더 좋습니다. 반명 auto_ptr은 복사되는 객체(원본 객체)를 null로 만들어 버립니다.

 자원 관리 객체의 대표적인 예로는 auto_ptr이라는 Smart Pointer가 있다. 자원 관리 객체를 사용하는 방법의 중요한 두 가지 특징은 다음과 같다.

 첫째, 자원을 획득한 후에 자원 관리 객체에게 넘깁니다.
 둘째, 자원 관리 객체는 자신의 소멸자를 사용해서 자원이 확실히 해제되도록 합니다.

 위의 Code를 auto_ptr을 이용하게끔 수정하면 다음과 같다.

void f() {
    std::auto_ptr<Invest> pInv(new Invest());
    ...
}

 auto_ptr의 경우 복사를 하면 원본 객체를 null로 만들어 버린다. 복사를 해야할 일이 발생한다면 참조 카운팅 방식 스마트 포인터 (reference-counting smart pointer : RCSP)가 좋다. 대표적인 RCSP로는 TR1에서 제공하는 tr1::shared_ptr이 있다.

shared_ptr에 대한 자세한 설명은 아래 글을 참조하기 바란다.

[STL] shared_ptr, weak_ptr

 auto_ptr, shared_ptr 의 경우 소멸자 내부에서 delete를 사용하므로, delete []가 필요한 배열을 사용하면 안된다. 배열을 꼭 써야겠다면서 밤잠을 못 주무시는 분들은 Boost에 있는 boost::scoped_array 와 boost::shared_array가 있다.

 Smart Pointer 로 해결이 안된다면 자원 관리 클래스를 직접 만들수밖에 없다. 영장류의 능력을 초월해야 할 만큼의 어려운 일은 아니지만, 각별히 신경을 써야 할 부분이 많으므로 세심함이 필요하다.

댓글 없음:

댓글 쓰기