close

C++ void *的陷阱-解構失敗

考慮以下的程式

//test.h
class A
{
    public:
        A(){cout<<"A constructor."<<endl;}
        ~A(){cout<<"A destructor."<<endl;}
};

class B
{
    public:
        void *m_pObj;
    public:
        B()
        {
            m_pObj = 0;
            cout<<"B constructor."<<endl;
        }
        ~B()
        {
            if(m_pObj)
            {
                delete m_pObj;
                m_pObj = 0;
            }
            cout<<"B destructor."<<endl;
        }
};

//main.cpp
int main()
{
    B *pB = new B();
    pB->m_pObj = (void*)(new A());
    delete pB;
    system("pause");
    return 0;
}

執行結果

B constructor.
A constructor.
B destructor.

 

咦?A destructor.不見了?
明明就有 B destructor. ,可是卻沒有 delete A ?

主要原因就在於,A 在 B 裡的型別是 void ,而不是 class A,所以在解構時就不會執行到 class A 的 destructor。一旦 B 的數量變多時,裡面的 A 又沒有辦法解構,記憶體很快就會被吃光了,造成非常嚴重的 memory leak。

會出現這種程式碼其實是因為要存放不同型別的資料,或許有人會說就用多型就好了啊,但問題是當一個專案經過了五六年後,根本動不了那個繼承架構,所以才會出現這種折衷方案。

解決方法就是,既然一開始就是在外部 new A 再轉型成 void,那就只好拿出來再轉回 A,再去 delete。

int main()
{
    B *pB = new B();
    pB->m_pObj = (void*)(new A());
    delete (A *)pB->m_pObj;
    pB->m_pObj = 0;
    delete pB;
    system("pause");
    return 0;
}

執行結果

B constructor.
A constructor.
A destructor.
B destructor.

arrow
arrow
    文章標籤
    C++ void
    全站熱搜

    kamory 發表在 痞客邦 留言(0) 人氣()