2009-12-16 78 views
1

注意:這不是家庭作業IT與提供給我們按我們的教授模擬考試來幫助我們準備我們的考試寫作,檢查在C內存泄漏++測試用例

我目前正在研究編程考試。在他們給我們的樣本測試之一中,我們有以下問題:

假設您已獲得一個模板化容器,該容器包含無序的對象集合。

template <typename T> 
class Container { 
    public: 
     void insert(T *op); 
     // EFFECTS: inserts the object pointed to by op into 
     // the container 
     T *remove(); 
     // EFFECTS: removes an object from the Container, and 
     // returns a pointer to it. Returns NULL if no 
     // objects remain in the Container. 
     // Note: the implementation can choose which 
     // object to return if more than one exists. 
     Container(); // ctor 
     Container(const Container &l); // copy ctor 
     Container &operator=(const Container &l); // assignment 
     ~Container(); // dtor 
    private: 
     ... 
}; 

請注意,這只是接口;爲簡潔起見,省略了實施細節。然而,你可能會認爲實現是基於節點的;鏈接的節點集合 保存對象。

您懷疑析構函數的實現不滿足最不變式的保守規則,而是正在泄漏內存。寫一個驗收測試(類似於項目4)來檢查這種情況。您必須提供合適的包含類型和執行測試的主體。

請注意,您不能依賴任何語言未定義的行爲,您可能不需要 假定您有來自Project 5的altnew分配器可供您使用,並且您可能不會 覆蓋delete操作符。提示:您可以使用全局變量。

不過,我覺得是這樣的:

#include <iostream> 

using namespace std; 

int *p = NULL; 

void leak() { 
    int *num = new int(5); 
    p = num; 
    delete num; 
} 

int main() { 
    if ((*p = 6)) { 
     cout << "Memory leak\n"; 
    } else { 
     cout << "No Leak\n"; 
    } 
} 

這背後的基本思想是我,雖然我寫不出來,我還沒有分配的內存空間。在編譯這個測試代碼時,雖然它的工作很好,但顯然你可以。有關如何編寫這樣的測試用例的想法?

+0

自己所想的測試依賴於不確定的行爲。當您訪問free'd內存時會發生什麼情況未定義。 – 2009-12-16 20:16:07

+0

我想你可以用'Container <使用全局變量計算它本身的實例>'進行測試。 – UncleBens 2009-12-16 20:22:09

+0

你可能想解釋Project 5中的「altnew」分配器是什麼。也許這爲您提供了跟蹤分配的工具。 – 2009-12-16 20:34:20

回答

4

如果您創建一個類用作模板參數,該參數將在其構造函數中將1添加到全局變量中,並在其析構函數中將該全局變量減1,該怎麼辦?

然後,你可以在容器上執行任何你想要的測試(創建它,填充它,清空它,刪除它等),並通過在容器被銷燬後檢查全局變量爲0來檢查內存泄漏。

5

當你說:

void leak() { 
    int *num = new int(5); 
    p = num; 
    delete num; 
} 

沒有內存泄漏。然而,如果解除引用,懸掛指針(p)會導致未定義的行爲。

+0

對。你看,我認爲當你使用刪除命令時,它會釋放,你將不能再寫入該內存地址。我測試了我的程序,編譯時使用了和不使用delete num程序,但是在兩種情況下都表示沒有內存泄漏。對於實際的考試,我不得不使用給予我們的方法,但這段代碼只是爲了測試顯然無效的概念。 – blcArmadillo 2009-12-16 20:24:08

+0

刪除num程序=刪除num行 – blcArmadillo 2009-12-16 20:24:58

+0

一旦刪除,如果你寫入內存你有什麼C++調用「未定義的行爲」 - 任何事情都可能發生。你的代碼甚至可能似乎工作。但沒有泄漏。 – 2009-12-16 20:29:51

0

我不確定項目4和項目5中列出的是什麼,但我認爲這樣做的方法是爲插入到容器中的對象分配一個全局指針(按提示)。如果你然後銷燬容器,它應該銷燬其中的對象,並且該全局指針現在應該爲空。

+1

不會。全局指針不會受到刪除容器的影響,它只會是懸掛的,如果取消引用則會失敗 - 這可能是需要的。實施留給學生練習。 :-) – 2009-12-16 20:27:00

+0

這就是我的意思 - 測試它是否失敗。如果它沒有失敗,那麼它是泄漏的。 – aronchick 2009-12-18 21:01:31

0

您可以在T構造函數中遞增一個整型全局變量,並在T析構函數中遞減它:這樣做會告訴您T實例是否被容器銷燬。驗收測試可以將一些T實例分配到一個Container實例中,銷燬該Container,並測試是否銷燬了T實例(即是否調用了T析構函數)。

沒有重寫delete運算符我沒有看到一個簡單的方法來告訴是否容器不僅破壞牛逼的實例,但也釋放出的T實例佔用內存:但如果破壞牛逼實例(其中你可以按照上面的第一段所述進行測試),那麼你可能會希望它的可能是也釋放每個實例佔用的內存。

0

我會使用一個包含引用計數的類型。在容器中插入物品時,引用計數應該增加。當你銷燬容器時,它應該遞減到它的初始值。引用計數可以保存在全局變量(如建議)或類中的靜態變量(我通常使用後者,但稍微複雜一些)。

+0

感謝您的信息。你的意思是在插入和解構方法的實現中添加該代碼嗎?如果是這樣,我不認爲我可以做到這一點,因爲我沒有編寫方法實現。 – blcArmadillo 2009-12-16 20:50:06

+0

否 - 這將全部存儲在被存儲的對象中。正常情況下,它在該課程中完成'ctors和dtor - 每個ctor增加計數,並且dtor減少計數。另一種可能性是讓ctors和dtors在打印字符串時說出它們的運行時間。 – 2009-12-16 21:01:11

4

你可以使用一個元素類像這樣的,這也將它的實例:

class InstCounter { 
public: 
    static int counter; 
    InstCounter() { counter++; } 
    ~InstCounter() { counter--; } 
}; 
int InstCounter::counter = 0; 

int main(int argc, char** argv) 
{ 
    { Container<InstCounter> c; 
    // insert elements... 
    c.insert(new InstCounter); 
    } // calls dtor of c 
    if (InstCounter::counter > 0) 
    std::cout << "Container is leaking." << std::endl; 
    return 0; 
} 
+0

這與我的想法是一致的。但是,使用靜態成員變量可能比我對全局變量的建議更優雅。加Wolfgang實際上寫出了代碼:)所以使用這個! – 2009-12-17 03:02:39