2009년 11월 5일 목요일

리소스 관리를 위한 객체 사용

리소스를 동적으로 할당해서 사용하는 것은 상당히 번거로운 일이다. func1() 에서 Resource 라는 class에 대한 instance를 동적으로 할당해서 사용한다고 가정을 하자.

void func1()
{
    Resource rsc = new Resource();

    ...

    delete rsc;
}

... 에 해당하는 코드가 어떻게 구성이 되느냐에 따라서 rsc가 정상적으로 해제될 수도 있고, 아니면 memory leakage를 발생시킬 수가 있다. 즉, 이 영역에서 제대로 rsc를 해제시키지 않고, return을 해버리는 코드가 들어가게 되면 문제가 발생하게 된다.
이러한 리소스 문제를 개선시킬 수 있는 방법이 있다. STL 에서 제공하는 std::auto_ptr<T> 이나 std::tr1::shared_ptr<T> 을 이용하는 방법이다. 이 템플릿을 이용해서 auto instance를 생성하면, blace 영역을 벗어날 때, 자동으로 소멸자가 실행되면서, delete가 실행된다.

void func2()
{
    std::auto_ptr<Resource> rsc(new Resource());

    ...
     
}

void func3()
{
    std::tr1::shared_ptr<Resource> rsc(new Resource());

    ...
     
}

std::auto_ptr<T>와 std::tr1::shared_ptr<T> 의 차이는 copy 방법에 있다. 전자의 경우에는 copy가 되더라도 그 pointer의 갯수는 하나로만 유지하게 된다. 즉, copy가 되는 쪽에는 그 instance의 주소를 가지게 되지만, copy의 원본은 null 값으로 바뀌게 된다.

void func4()
{
    std::auto_ptr<Resource> rsc1(new Resource());
   
    std::auto_ptr<Resource> rsc2(rsc1);    // rsc1 은 null 이 되고, rsc2가 instance의 주소를 가지게 된다.

    rsc1 = rsc2;        // 다시 rsc1과 rsc2의 값이 swap 된다.
}

std::tr1::shared_ptr<T> 의 경우에는 일반 copy 기능과 동일하게 동작된다고 생각할 수 있다.

void func5()
{
    std::tr1::shared_ptr<Resource> rsc1(new Resource());
   
    std::tr1::shared_ptr<Resource> rsc2(rsc1);    // rsc2 는 rsc1 과 동일한 주소를 가지게 된다.
   
    rsc1 = rsc2;        // 변경사항이 없다.
}

중요한 내용은 copy 방법에 대한 것은 아니고, 자원을 영역에서 안전하게 해제를 해주는 방법으로 제안할 수 있는 것은 std::auto_ptr<T>, std::tr1::shared_ptr<T> 와 같은 도구를 이용하면, 일일히 blace에서 벗어날 때 동적으로 해제해줘야 하는 번거로움과 또한 빠뜨렸을 때 발생할 수 있는 memory leakage와 같은 문제를 덜 수 있다는 점이다.

댓글 없음:

댓글 쓰기