STL類指針容器container 元素clear 注意事項

在使用 STL 容器時, 涉及到 C++多態(polymorphism)和虛函數時,經常會遇到使用容器存儲類指針,當你要刪除某個元素或者(erase)或者清空容器(clear)時,直接調用 erase或 clear 函數,指針指向的內存並不會釋放,也就是說,對象不會被析構,這時就會導致內存泄漏(memory leak)。
示例代碼:

#include <iostream>
#include <list>

using std::cout;


class Base {
public:
    virtual ~Base() {}
};

class Derived : public Base {};


int main(int argc, char* argv[])
{
    using std::list;
    list<Base*> ls;
    ls.push_back(new Base());
    ls.push_back(new Derived());
    ls.push_back(new Base());
    ls.clear();
    return 0;
}

編譯後,使用內存檢測工具 valgrind運行內存泄漏檢測,得:
這裏寫圖片描述
從圖中可以發現程序中有三處內存泄漏,正對應着:

ls.push_back(new Base());
ls.push_back(new Derived());
ls.push_back(new Base());

可見,我們直接調用 clear()後指針對應的內存並沒有被釋放。而要消除內存泄漏,我們必須添加清理代碼,對程序做以下修改:

#include <iostream>
#include <list>

using std::cout;


class Base {
public:
    virtual ~Base() {}
};

class Derived : public Base {};


int main(int argc, char* argv[])
{
    using std::list;
    list<Base*> ls;
    ls.push_back(new Base());
    ls.push_back(new Derived());
    ls.push_back(new Base());

    //添加清理代碼
    for(list<Base*>::iterator it=ls.begin(); it != ls.end(); ++it)
        delete *it;

    ls.clear();
    return 0;
}

再次運行 valgrind, 我們可以發現原來的內存泄漏消失。
這裏寫圖片描述

有關 valgrind 的使用網上有很多,也可以查看本地幫助, 具體命令

valgrind --help

這裏只是簡單地開啓 –leak-check 選項,另外程序在編譯時加入“-g”選項,否則看不到發生內存泄漏的代碼位置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章