unordered_map:clear()不会在clear()上释放堆

时间:2017-03-01 10:55:01

标签: c++ memory-leaks heap-memory unordered-map dynamic-allocation

我在Solaris 10上使用g ++ 4.9.2使用unordered_map,但令人惊讶的是我发现clear()不会释放堆。 这是示例代码:

#include <iostream>
#include <unordered_map>

int main ()
{
  std::unordered_map<long long, long long> mymap;
  mymap.rehash(200000);
  getchar();
  for (int i = 0; i < 2000000; i++) {
    mymap[i] = i*i;
  }
  std::cout << "current bucket_count: " << mymap.bucket_count() << std::endl;
  std::cout << "current size: " << mymap.size() << std::endl;
  getchar();
  mymap.clear();
  std::cout << "current bucket_count: " << mymap.bucket_count() << std::endl;
  std::cout << "current size: " << mymap.size() << std::endl;
  getchar();
  return 0;
}

当progranm在getchar()上等待时,我正在观察程序的堆积。而且,这是通过pmap -x <PID> | grep heap

找到的堆快照
1. While waiting on 1st getchar(): `0002C000     792     792     792       - rwx--    [ heap ]`

2. After 1st getchar(): it prints:

    current bucket_count: 3439651
    current size: 2000000
Heap shows while waiting on 2nd getchar():

    0002C000    3920    3920    3920       - rwx--    [ heap ]
    00400000   73728   72272   72272       - rwx--    [ heap ]

3. After 2nd getchar(): it prints:

    current bucket_count: 3439651
    current size: 0
Heap shows while waiting on 2nd getchar():
0002C000    3920    3920    3920       - rwx--    [ heap ]
00400000   73728   72272   72272       - rwx--    [ heap ]

这表明(步骤3)clear()对堆没有影响。虽然,文档说,

std::unordered_map::clear
void clear() noexcept;
Clear content
All the elements in the unordered_map container are dropped: their destructors are called, and they are removed from the container, leaving it with a size of 0.

但是,我的堆数并没有反映出来。 有没有其他方法来释放unordered_map对象占用的堆?或者,我应该使用其他东西吗? 请指导如何从unordered_map释放内存?

3 个答案:

答案 0 :(得分:1)

地图内容已删除。与磁盘中的文件类似(仅从索引中擦除)。如果您可以在下次使用内存,那么释放内存将无效。

如果您不真正释放地图内存,则需要销毁整个对象。或者您可以尝试将void reserve( size_type count );调用为零。 (我还没试过)

答案 1 :(得分:1)

  

unordered_map:clear()不会在clear()

上释放堆

C ++标准不需要clear来释放内存。

  

但是,我的堆数并没有反映出来。

文档中没有提到堆。调用元素的析构函数,并且如您所确认的,大小为0.如果添加新元素,它们可能会重用先前清除的元素所使用的内存。

  

还有其他方法可以释放unordered_map对象占用的堆吗?

销毁地图肯定会释放所有内存。

mymap.rehash(0)也可能有用。

但是,仅仅因为内存被释放到实现(通过调用free),并不意味着实现必然会释放内存到操作系统。实现可能决定将内存重用于其他分配(尽管这只是小分配的典型情况)。

在C ++中没有标准的方法可以做到这一点,但Linux提供了一个函数malloc_trim,它将尝试将释放的内存从堆顶部释放到操作系统。

答案 2 :(得分:1)

内存未释放,因为地图应该继续使用,直到它超出范围或被删除。对于这个合理的默认用例,重新分配会导致不必要的开销。我的建议:

  • 如果确实不再需要它,请将其范围限制在您需要的范围内,分别使用适当范围的地图智能指针。
  • 如果您仍然需要它,但暂时不需要,或者只使用更少的元素,swap它会带有一个空的临时地图(然后会被删除)。
  • 明确调用析构函数并重新创建新映射。