프로그래밍/C/C++

소멸자 명시적 호출의 주의점 ?

nanze 2021. 12. 24. 11:58
반응형

 음 메모리 풀을 구현하다 경험한 것을 정리한다. 인터넷에서 검색을 해봐도 잘 보이질 않고 물어볼 사람도 없어서 추정의 글을 적는다. 

 혹시라도 누군가 본 후 틀렸다면 정보를 제공하면 고마울 것 같다. 일단 코드부터 보자.

template <typename T>
class NzOPool {
public :
    NzOPool(int nMaxSize = 20) : m_nMaxSize(nMaxSize){
        for(int i =0; i<m_nMaxSize; i++){
            T* pObj = (T*)malloc(sizeof(T));
            m_queObjs.push(pObj);
        }
    }
    
    ~NzOPool(){
        while( !m_queObjs.empty()){
            T* pObj = nullptr;
            if( m_queObjs.try_pop( pObj ) == true ){
                pObj->~T();
                free(pObj);
            }
        }
    }
    
    T* Pop() {
        T* pRet = nullptr;
        if( m_queObjs.try_pop( pRet ) == false){
            pRet = (T*)malloc( sizeof(T));
            ++m_nMaxSize;
        }
        new (pRet) T();  //생성자 명시적 호출
        return pRet;
    }
    
    void Push(T* pObj){
        pObj->~T();  // 소멸자 명시적 호출
        m_queObjs.push( pObj );
    }
    
private:
    std::atomic<int> m_nMaxSize;
    tbb::concurrent_queue<T*> m_quqObjs;
    
};

 위 코드는 tbb 의 병행성 큐를 이용하여 오브젝트 풀을 구현한 것이다. 문제는 템플렛 타입 T 가 무엇이냐이다. 아니 정확히 말하자면 저 T 가 무엇을 담고 있는 것이겠지.

만약 타입 T 가 다음과 같은 클래스라고 하자. 

class TestItem{
public:
    CString cstrA;
    CString cstrB;
    
    void TestFuncA(){    cstrA = _T("TEST");    }
};

 앞서 작성한 오브젝트 풀에서 객체가 큐에서 나왔다가 사용 후 다시 큐로 회수될 때 소멸자를 명시적으로 호출하고 있다. 이 때 내 생각은 소멸자가 명시적으로 호출하면서 클래스 내부의 멤버 변수들에도 영향을 주는 것 아닌가 생각된다. 멤버 변수가 단순히 클래스가 아닌 타입일 경우에는 문제가 없지만 클래스일 경우에는 다르다 생각된다. 작성된 오브젝트 풀을 테스트하면서 회수된 객체를 다시 사용할 경우 cstrA 변수에 할당하는 부분에 문제가 생격다. 힙이 깨진다는 크리티컬 에러 -ㅋ-;; 

 내가 생각한 유의할 점은 소멸자를 명시적으로 호출할 경우 대상 클래스가 무엇을 담고 있는지 유의해야 한다는 것이다. 어떤 서적이나 정보를 본 것이 아닌 추측이다. 아무튼 객체의 소멸이 아닌 재사용성을 위해 소멸자를 명시적으로 호출할 경우 대상 클래스가 무엇을 담고 있는지 꼭 확인하자. !!!!

반응형