2010-10-31 27 views
1

TL; DR刪除自定義陣列導致堆錯誤

升壓試驗框架崩潰,並沒有同時通過所有測試和泄漏的所有內存給定的錯誤。

測試失敗多次提到的析構函數實現。清除函數也會拋出堆錯誤。

我們在做什麼錯誤的dtor?

TL; DR

這是關於大學家庭作業,和我的朋友的解決方案,說問題。爲了獲得更多的C風格指針和更低級的編程風格,我們需要實現我們自己的動態數組。

根據我們老師的900-LOC Boost-Test Framework,他的任務是完整的並且功能完整。唯一的問題是當測試退出或調用實現的dtor時崩潰(或堆錯誤,因爲沒有真正的錯誤消息彈出)。

他的動態數組使用三個指針:pFirst, pLast and pEnd,指向數組的第一個元素,指向數組中最後一個元素的指針,分別指向數組中最後一個尚未分配的元素。

只要他不試圖刪除任何指針,他的程序就會通過。這是一個壞主意,但嘿,它讓他通過任務。目前。

我的朋友已經嘗試了幾次實現析構函數,但它們都會導致堆錯誤並導致測試框架失敗。

// Teacher's recommended dtor. 
Field::~Field() 
{ 
    for(int i(0); i != this->size(); ++i) 
     (pFirst+i)->~T(); 
    delete pFirst; 
    pFirst = pLast = pEnd = NULL; 
} 

// My recommendation to friend. 
Field::~Field() 
{ 
    delete[] pFirst; 
    pFirst = pLast = pEnd = NULL; 
} 

崩潰都與同一個堆錯誤。

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 

測試一個典型的鏈是這樣的:

BOOST_AUTO_TEST_CASE(TEST_clear) 
{ 
    Field f(3, 4.0f); 
    f.clear(); // Error here IF we use delete in the clear method. 
    BOOST_CHECK(f.size()==0); 
    BOOST_CHECK(f.capacity()==4); 
} // Error here; during destruction IF we have implemented the dtor. 

當我們嘗試更換陣列Clear方法發出了同樣的錯誤,所以我們只是有:

void Field::clear() 
{ 
    size_t capa = capacity(); 
    T *temp =pFirst; 
    pFirst = new T[capa]; 
    pLast = pFirst; 
    pEnd = pFirst+capa; 
} 

什麼我們是否對dtor做了錯誤,清楚並且一般在處理刪除指針時?

+0

@Pointy:他現在修正了一個錯誤:P – IAE 2010-10-31 15:53:39

回答

3

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)表示堆損壞。通常它會在您分配內存的末尾寫入時發生。 我在代碼中看到以下問題:在Field::clear中,您將指針指向分配的內存,存儲在pFirst中,並立即由pLast覆蓋它。我認爲你應該改爲pLast = pFirst;

老師推薦的dtor對我沒有意義。如果您使用new[]進行分配,然後使用delete[]進行取消分配,請勿分別調用每個析構函數並使用delete

+0

爲了澄清,你還想對每個對象調用delete,對吧?我同意手動調用每個對象上的析構函數的奇怪之處。 – MintyAnt 2013-02-09 07:24:22

+0

@MintyAnt:不可以。由於'new T []'用於分配數組,所以應該使用delete []來釋放整個數組。在每個對象上調用delete都是一個錯誤。 – vitaut 2013-02-09 14:30:45

2

如果pFirst指向數組的第一個元素,那麼你的「老師推薦的dtor」是錯誤的。你需要說delete[] pFirst來釋放數組。

但是有很多問題可能導致這種情況,比如由其他函數引起的堆損壞。嘗試在內存損壞檢查程序(如Valgrind)中運行此操作,以查看是否溢出了堆緩衝區。