2013-03-06 105 views
2

我在使用C++中的內置指針時遇到了問題。當我的程序終止時,我的類的析構函數全部被調用。我有一個數據類,隊列類,並結合其他數據類使用如下隊列(介意飛粗糙編碼):C++避免刪除內存兩次

class Data { 
    int x; 
} 

class Queue { 
    class Node { 
    Data* x; 
    } 
    Node* head; 
} 

class C1 { 
    Queue q; 
} 

class C1Queue{ 
    class Node { 
    C1* c; 
    } 
    Node* head; 
} 

我也有另外一個隊列,Q2,不存在在一個對象中。我從文件加載兩個隊列,所以我說的線沿線的東西(假設cQueue是C1Queue):持有指針到每個

Data *d = new Data(0); 
q2->pushBack(d); 
C1 c = new C1(); 
cQueue->pushBack(c->pushBack(d)); 

正如你所看到的,我有兩個隊列(Q2)數據,以及一個隊列中持有指向q2相同數據的隊列的對象。 現在,當我的程序終止時,我希望所有數據都被釋放。但是,在解除分配對象時,首先解除分配q2,然後解除分配C1對象,然後將其隊列解除分配,然後刪除與剛刪除的q2相同的數據。或者另一種情況是首先解除分配對象(我不確定發生了哪種排序),然後解除分配q2並將其運行到已刪除的內存中。

所以問題是內存空間被刪除兩次,這是不好的。一旦內存被刪除,它將被釋放給其他程序使用,因此再次刪除該內存空間將導致seg故障。

也許我錯過了這裏的東西,但我不知道如何做到這一點沒有一個特殊類型的指針(我不能使用一種特殊類型的指針)。

我能想到的唯一方法是阻止C1對象釋放其隊列但釋放其餘部分,但我不知道該怎麼做。如果有人可以幫助我,那麼我會非常感激。

+4

請注意,對空指針使用'delete'是一個安全操作(通常它什麼都不做)。這就是爲什麼強烈建議在'delete'd之後將空指針設置爲'NULL'或者更好的'nullptr'。 – 2013-03-06 03:41:53

+0

這是真的,但刪除已釋放的內存空間將導致大多數編譯器出現分段錯誤(因爲已將內存分配給管理該內存的任何內存) – 2013-03-06 03:45:11

+3

哦,上帝,等待shared_ptr球員運行至於你的問題,通常是以創建它們的相反順序銷燬對象通常是一個好主意。除了多線程代碼之外,這應該是可能的。您還需要決定誰擁有對象以及誰僅僅使用它們 – James 2013-03-06 03:46:20

回答

1

既然你(顯然)使用細微防止像std::shared_ptr,你可以嘗試以下三個補救措施之一:

  • 手冊引用計數。強制每次將一個Data推入隊列,其隊列的引用次數將遞增,並且將清除Queue時的遞減計數。當引用計數爲零時,delete this(但請確保始終在堆上分配Data!)
  • 指定一個對象以「擁有」Data元素。只有該對象可以銷燬Data(你甚至可以用私有析構函數和朋友類來強制執行此操作)。您可能需要不止一個。 (如果你是這個代理人的代理人,這會變成一個窮人的std::shared_ptr)。
  • 讓你的Data是可複製的,只需用全新的對象完成任何事情。這適用於少量不需要保持同步的數據(例如,一個持有兩個整數的Point2D類)。
+0

非常感謝!該計數策略是爲我工作的策略。順便說一下,強制在堆上分配的方法是創建一個標誌來指定它是否被動態分配,如果標誌條件成立,則刪除該對象。無論如何,這救了我一個頭痛的世界,再次感謝! – 2013-03-06 04:25:17