map值存的是指针
map自带的clear()函数会清空map里存储的所有内容,但如果map值存储的是指针,则里面的值不会被清空,会造成内存泄漏,所以值为指针的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(); //值为指针不要这样删除
调用clear()函数之前先把值里的指针的值通过迭代器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中存储的是智能指针
若是采用了智能指针,则无需单独delete,智能指针,会自动释放内存
std::map<int, std::shared_ptr<int>> m_map;
m_map[0] = std::make_shared<int>();
delete m_map[0]; //错误
清空map释放内存
若需要多次使用同一个map,其中每次使用后都clear清空,多次之后,可能出现内存泄露,这是因为map的空间便没有释放,所以得使用swap清空。
如果内存错误提示如下
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容器调用clear()方法,通常只是使得容器内部的对象通通析构,但容器本身的内存无法得到释放。即篮子里面东西拿走了,篮子占的空间还在,这样是为了方便下次存放新的对象时,不需要再次申请空间。即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();
}
就单单实现某个map清空来说,swap效率最高,几乎是0耗时。但是当退出整个函数,释放swap转移到的临时对象要耗一定的时间。erase效率稍微比clear高。通过for循环erase好似效率又高点。
对于map、set、unordered_map等容器,调用clear()、swap()都无法使得内存真正释放。虽然很多地方谈到,这一现象(内存被保留下来)是正常的,并不需要担心。但是当大量使用堆内存存放不同的数据结构,会造成严重的内存碎片从而导致内存泄漏问题。文章来源:https://www.toymoban.com/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);
这一行代码会将空闲的堆内存归还给操作系统,供其他进程使用。文章来源地址https://www.toymoban.com/news/detail-700745.html
到了这里,关于C++ map clear内存泄漏问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!