在使用 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”選項,否則看不到發生內存泄漏的代碼位置。