为啥我的 unordered_map 越来越大

Posted

技术标签:

【中文标题】为啥我的 unordered_map 越来越大【英文标题】:why is my unordered_map getting bigger and bigger为什么我的 unordered_map 越来越大 【发布时间】:2020-12-27 18:43:25 【问题描述】:

我用的是unordered_map,key是string,value是一个class IpsegInfo。 我读取了一个文件并使用文件数据来更新map中的值,map的大小总是一样的,但是内存中的map空间越来越大。

我的代码每 30 分钟从文件中更新一次地图,文件有 1000 万行,长度从未改变,只有数据会改变。所以我的地图长度也总是一千万。文件物理大小为 500MB,第一次加载后 unordered_map 内存大小为 4GB,但几个小时后,map 大小变为 50GB,并且不断变大,我想我应该是在某个地方发生了内存泄漏。

我的代码如下:

class IpsegInfo 
    public:
        string country;
        string province;
        string isp;
        string asn;
        IpsegInfo();
        IpsegInfo(string country, string province, string isp, string asn);
        ~IpsegInfo();
;
//one thread is doing the map refresh. other threads read the map for quick access.
unordered_map<string, IpsegInfo> IpsegMap::map;
void refresh()
  while(1)
   string line;
   string delim = ",";
   ifstream ipsegFile("/opt/test/ipseg.txt");
   if(ipsegFile.is_open())
     while (getline(ipsegFile,line) )
        trim(line);
        vector<string> ss = comUtil.split(line,delim);
        IpsegInfo *info = new IpsegInfo(ss[1],ss[2],ss[3],ss[4]);
        map[ss[0]] = *info;
     
   
   ipsegFile.close();
   sleep(60*30);
   

【问题讨论】:

这块内存在哪里被释放:IpsegInfo *info = new ... @Jarvis map 不是关键字,实际上是 C++ 程序完全合法且合法的变量名。 map[ss[0]]IpsegInfo 类型的对象。它不是一个指针。这不是你分配的东西。在refresh 函数中,info 是一个指向你已经分配的东西的指针,但你从来没有delete 它。解决方法是根本不使用new 或临时的info 变量,直接赋值给map[ss[0]] @Jack 你需要做的是找出哪个数据结构拥有你分配的内存,以及何时释放它。 @Someprogrammerdude 问题不在于不必要的局部变量info,而在于分配的内存,它永远不会被释放。 【参考方案1】:
        IpsegInfo *info = new IpsegInfo(ss[1],ss[2],ss[3],ss[4]);
        map[ss[0]] = *info;

在这里,您使用 new 创建一个 IpsegInfo。这意味着您还应该使用delete 将其删除。 相反,您只需覆盖它,就会造成内存泄漏。使用 RAII 自动管理您的数据:

        IpsegInfo info = IpsegInfo(ss[1],ss[2],ss[3],ss[4]); // no pointers!
        map[ss[0]] = info;

【讨论】:

甚至不需要info 变量。 @Someprogrammerdude 是的。我把它留在那里,这样更改会更容易看到。另外:using namespace std 被认为是不好的做法! @Someprogrammerdude 我刚试过,它有效,非常感谢!为什么在使用new IpsegInfo()时没有被覆盖,但是没有new就被覆盖了?顺便说一句,我应该在插入之前使用 map.erase() 吗? @Jack — 当您使用new 创建一个对象时,您有责任在完成后销毁它。如果您不想发生内存泄漏,则必须在某个时候将其删除。您可以在分配给map[ss[0]] 后使用delete info; 消除泄漏,但此答案中的解决方案是更好的方法。让编译器处理簿记以销毁对象。

以上是关于为啥我的 unordered_map 越来越大的主要内容,如果未能解决你的问题,请参考以下文章

std::unordered_map::operator[] - 为啥有两个签名?

为啥我不能增加 std::unordered_map 迭代器?

SQL Server为啥日志文件越来越大

为啥 unordered_map 需要散列而不是地图?

为啥我不能用一对作为键来编译 unordered_map?

为啥我不能用一对作为键来编译 unordered_map?