如何释放unordered_map内存?

时间:2017-02-08 13:08:20

标签: c++ memory memory-management memory-leaks

问题

我已经看到使用map.clear()map.rehash(0)并没有从我的RAM中释放预期的内存。

我使用以下代码创建了一个程序:

int main() {
    std::unordered_map<std::string, int> m1;
    std::unordered_map<std::string, int> m2;

    // fill the maps m1 and m2 with 5 million elements

    // bucket_count = 5098259; size = 5000000

    // now I clear m1
    m1.clear();
    m1.rehash(0);
      // m1: bucket_count = 2; size = 0
      // m2: bucket_count = 5098259; size = 5000000

    // now I clear m2
    m2.clear();
    m2.rehash(1);
      // m1: bucket_count = 2; size = 0
      // m2: bucket_count = 2; size = 0
}

根据程序的每个步骤之后的bucket_countsize,似乎RAM中释放了大量空间。但是,检查系统监视器使用的RAM,我得到以下演变ram evolution

问题

即使清除并重新映射两个映射,内存也只在程序完成时释放。实际上只有很少的内存释放,但我不确定是否有可能在图片中看到。怎么可能?

如何从RAM中实际释放内存?

上下文

我正在使用动态编程算法来解决Linux中4Gb RAM的旅行商问题。它由于内存不足而崩溃,所以我试图优化程序使用的内存。

经过一些改进后,我保留了两个unordered_map

  • 费用:存储上一次迭代的值
  • new_costs :在该次迭代期间构建。

迭代结束后,我交换它们,因此费用有新的计算值,我清除 new_costs 尝试释放内存并启动建立下一个迭代。

代码是这样的:

std::unordered_map<std::string, int> costs(5098259);
std::unordered_map<std::string, int> new_costs(5098259);

for (int m = 1; m <= n; m++) {
  new_costs.clear();
  new_costs.rehash(5098259);

  while (something) {
    // I build the content of new_costs based on the content of costs
  }

  std::swap(costs, new_costs);
}

最多我将分别存储2496144和2704156个元素。这样就可以同时存储 5200300 元素。鉴于密钥是一个最多70个字符的字符串--71个字节 - 并且存储的值是一个浮点数--4个字节 - 我将存储大约380 Mb。

我知道unordered_map不是内存效率高,但是程序完全使用了我的RAM和我的交换内存,所以我必须遗漏一些东西。


**编辑可能的重复

How do I force my std::map to deallocate memory used?

我一直在使用C ++一周左右,我不知道std::mapstd::unordered_map的内存管理是否相同,或者它们之间是否存在相关差异。

我也不知道 deallocate 是否与释放对象使用的内存完全相同,因此可用的内存更多。

如果两者相同,我基本上都会问同样的问题。但是,在任何情况下,该问题的答案都解释了内存保留背后的原因,而不是为其提供解决方案。

2 个答案:

答案 0 :(得分:3)

您需要担心三个级别的内存使用,并且您的进程内存占用可能会显示错误的内存。

  1. 正在使用的内存

    您的容器中使用的东西。容易。

  2. 每个容器分配器

    您的容器有一个分配器。这可能决定分配比请求更大的块,并且还可以保持释放的存储器以供稍后重用。这两种方法通常都会以内存使用为代价提高速度。

    您可以使用交换技巧释放此缓存:创建一个空的临时容器,然后std::swap。这也会移动分配器,这意味着当临时超出范围时,将释放任何旧的高速缓存存储。

    对于释放的某些值,无论如何:内存可能会返回到你的......

  3. 流程范围的动态分配器(通常是“堆”)。

    由于完全相同的原因,这可能决定将内存缓存在您的进程中。它没有义务将该内存返回给系统(直到您的进程退出)。

  4. 强制程序将内存返回系统的唯一方法是编写自己的分配器,使用适当的系统调用来明确地执行此操作。

    在具有虚拟内存的系统上推理程序内存使用的明智方法是担心使用了多少内存并且不必担心其虚拟地址空间的大小

    NB。如果内存使用不断增长,尽管您清除并重新使用容器,您可能有泄漏或正在遭受内存碎片。这确实是个问题。当内存使用在运行期间没有减少时,这是完全正常的,无需担心。

答案 1 :(得分:0)

我们如何从像你这样的stl容器中释放内存,就是将它们换成空的容器。您可以使用此模板:

${short_description}

而不是打电话:

template<typename T>
inline void freeContainer(T& p_container)
{
    T empty;
    using std::swap;
    swap(p_container, empty);
}

你打电话

new_costs.clear();