map值存的是指針
map自帶的clear()函數(shù)會清空map里存儲的所有內(nèi)容,但如果map值存儲的是指針,則里面的值不會被清空,會造成內(nèi)存泄漏,所以值為指針的map必須用迭代器清空。
使用erase迭代刪除
迭代器刪除值為指針的map,一定要注意迭代器使用正確,一旦迭代器失效程序就會崩潰。
std::map<int, HHH*> test_map;
HHH* h1 = new HHH;
HHH* h2 = new HHH;
test_map[0] = h1;
test_map[1] = h2;
// 刪除
std::map<int, HHH*>::iterator iter;
for (iter = test_map.begin(); iter != test_map.end();)
{
delete iter->second;
iter->second = nullptr;
// 刪除迭代器元素先加加再刪,否則迭代器失效程序崩潰?。?!(必須iter++不可以++iter)
test_map.erase(iter++);
}
map值存儲的不是指針
std::map<int,int> test_map;
test_map[0] = 0;
test_map[1] = 0;
// 刪除
test_map.clear(); //值為指針不要這樣刪除
調(diào)用clear()函數(shù)之前先把值里的指針的值通過迭代器delete
std::map<int, HHH*> test_map;
HHH* h1 = new HHH;
HHH* h2 = new HHH;
test_map[0] = h1;
test_map[1] = h2;
// 刪除
std::map<int, HHH*>::iterator iter;
for (iter = test_map.begin(); iter != test_map.end();)
{
delete iter->second;
iter->second = nullptr;
// 刪除迭代器元素先加加再刪,否則迭代器失效程序崩潰?。?!(必須iter++不可以++iter)
iter++;
}
test_map.clear();
map中存儲的是智能指針
若是采用了智能指針,則無需單獨(dú)delete,智能指針,會自動釋放內(nèi)存
std::map<int, std::shared_ptr<int>> m_map;
m_map[0] = std::make_shared<int>();
delete m_map[0]; //錯誤
清空map釋放內(nèi)存
若需要多次使用同一個(gè)map,其中每次使用后都clear清空,多次之后,可能出現(xiàn)內(nèi)存泄露,這是因?yàn)閙ap的空間便沒有釋放,所以得使用swap清空。
如果內(nèi)存錯誤提示如下
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00000000010ca227 in tcmalloc::SLL_Next(void*) ()
(gdb) bt
#0 0x00000000010ca227 in tcmalloc::SLL_Next(void*) ()
#1 0x00000000010ca2b8 in tcmalloc::SLL_TryPop(void**, void**) ()
#2 0x00000000010ca715 in tcmalloc::ThreadCache::FreeList::TryPop(void**) ()
#3 0x00000000011ebe6c in tc_newarray ()
STL容器調(diào)用clear()方法,通常只是使得容器內(nèi)部的對象通通析構(gòu),但容器本身的內(nèi)存無法得到釋放。即籃子里面東西拿走了,籃子占的空間還在,這樣是為了方便下次存放新的對象時(shí),不需要再次申請空間。即clear()后,容器的size為0,但capacity不變。通過swap()空容器,來徹底釋放容器占用的capacity。
#include<map>
#include<vector>
#include<string>
#include <iostream>
#include <time.h>
using namespace std;
class useTest
{
public:
useTest() {};
map<string,string> testMap;
vector<string> testVertor;
string id;
};
void clearData(map<int, useTest>& needClearMap)
{
clock_t startt = clock();
//分別通過去注釋測試下面四種情況
//使用clear
//needClearMap.clear();
//使用swap
map<int, useTest> uu;
needClearMap.swap(uu);
//使用erase
//needClearMap.erase(needClearMap.begin(), needClearMap.end());
//使用for erase
//for (auto iter = needClearMap.begin(); iter != needClearMap.end(); iter = needClearMap.erase(iter)) {}
double sec = double(clock() - startt) / CLOCKS_PER_SEC;
std::cout << "In Clear Cost Time:" << sec << endl;
}
void test()
{
map<int, useTest> needClearMap;
for (size_t i = 0; i <= 10000; ++i)
{
useTest uT;
for (size_t ii = 0; ii <= 1000; ++ii)
{
uT.testMap[to_string(ii)] = "我是測試,我是測試,我就是測試string";
uT.testVertor.push_back("我也是測試,我也是測試,我就是測試string");
}
uT.id = to_string(i);
//cout << i << endl;
needClearMap[i] = uT;
}
clock_t startt = clock();
clearData(needClearMap);
double sec = double(clock() - startt) / CLOCKS_PER_SEC;
std::cout << "clearData Cost Time:" << sec << endl;
}
int main()
{
for (size_t i = 0; i < 10; ++i)
{
test();
}
getchar();
}
就單單實(shí)現(xiàn)某個(gè)map清空來說,swap效率最高,幾乎是0耗時(shí)。但是當(dāng)退出整個(gè)函數(shù),釋放swap轉(zhuǎn)移到的臨時(shí)對象要耗一定的時(shí)間。erase效率稍微比clear高。通過for循環(huán)erase好似效率又高點(diǎn)。
對于map、set、unordered_map等容器,調(diào)用clear()、swap()都無法使得內(nèi)存真正釋放。雖然很多地方談到,這一現(xiàn)象(內(nèi)存被保留下來)是正常的,并不需要擔(dān)心。但是當(dāng)大量使用堆內(nèi)存存放不同的數(shù)據(jù)結(jié)構(gòu),會造成嚴(yán)重的內(nèi)存碎片從而導(dǎo)致內(nèi)存泄漏問題。文章來源:http://www.zghlxwxcb.cn/news/detail-700745.html
#include <iostream>
#include <map>
#include <malloc.h>
using namespace std;
void func()
{
map<int,string> mp;
int i = 5000000;
while(i--)
mp.insert(make_pair(i,string("hell000o")));
map<int,string>().swap(mp); //swap
}
int main()
{
func();
cout <<"done."<<endl;
malloc_trim(0);
while(1);
}
只需添加一行,malloc_trim(0);
這一行代碼會將空閑的堆內(nèi)存歸還給操作系統(tǒng),供其他進(jìn)程使用。文章來源地址http://www.zghlxwxcb.cn/news/detail-700745.html
到了這里,關(guān)于C++ map clear內(nèi)存泄漏問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!