如何强制我的 std::map 释放使用的内存?

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

提问人:monkeyking 提问时间:4/13/2010 最后编辑:monkeyking 更新时间:9/30/2022 访问量:18463

问:

我正在使用 std::map,但我似乎无法将内存释放回操作系统。它看起来像,

int main(){
  aMap m;

  while(keepGoing){
    while(fillUpMap){
       //populate m
    }
    doWhatIwantWithMap(m);
    m.clear();//doesnt free memory back to OS

    //flush some buffered values into map for next iteration
    flushIntoMap(m);
  }
}

每个 (fillUpmap) 分配大约 1gig,所以我非常有兴趣在它吞噬我所有内存之前将其返回我的系统。

我在 std::vector 上也有同样的经历,但在那里我可以通过与空的 std::vector 进行交换来强制释放它。这不适用于地图。

当我使用 valgrind 时,它说所有内存都已释放,因此这不是泄漏的问题,因为运行后一切都会很好地清除。

编辑:

冲洗必须在清除后出现。

C++ 内存 STL 向量 字典

评论

1赞 MSalters 4/13/2010
请注意,当您尝试分配内存时,您的操作系统可能会分配地址空间,但仅在您触摸内存时分配实际的物理 RAM。如果您不再使用该 RAM,但其他程序需要它,则其内容将被交换到磁盘。因此,释放内存实际上释放了 RAM。

答:

2赞 Ferruccio 4/13/2010 #1

如果在堆上创建映射(通过 new),则删除它将释放它使用的任何内存。

3赞 martsbradley 4/13/2010 #2

这种行为是正常的,运行时库将映射类分配的内存保留给进程,以便下次需要分配内存时不必转到操作系统。这是一个运行时库优化。

17赞 Roger Pate 4/13/2010 #3

m.clear()将内存释放回堆,但堆实现通常不会将其释放回 OS(即使可以,碎片等问题也很难实现)。

这就是默认分配器的工作方式,如果您为地图指定了自己的分配器,它可能有自己的缓存。但是,即使在这种情况下,也应该对其进行缓存,以便立即重用。

地图不像矢量那样具有容量与大小的概念。

1赞 JRL 4/13/2010 #4

也许您可以创建一个自定义分配器,或者只使用 Boost 的池库。

1赞 user184968 4/13/2010 #5

当我将一些数据放入 std::map 中,然后调用 std::map::clear() 时,我做了一个简单的测试。

typedef std::map<int, unit_t,std::less<int>,  
     my_allocator<std::pair<const int, unit_t>, 4 > > contaner_t;
contaner_t keys;
keys[1] = 10;
keys[2] = 20;
keys[3] = 30;
keys.clear();

这是我的测试中插入的 printf 的结果:

Allocator # 4, Memory consumption:      56     (allocated   :       56)
Allocator # 4, Memory consumption:     112     (allocated   :       56)
Allocator # 4, Memory consumption:     168     (allocated   :       56)
Allocator # 4, Memory consumption:     112     (deallocated :       56),
Allocator # 4, Memory consumption:      56     (deallocated :       56),
Allocator # 4, Memory consumption:       0     (deallocated :       56),

我认为您可能还应该检查您的分配器行为,但我认为您的默认 std::allocator 实际上会按照您的预期释放内存,但该内存不会返回给操作系统。顺便问一下,你用什么操作系统?

这里的问题是你如何衡量,你怎么能确定你是否真的确定分配的内存实际上回到了操作系统?can't seem to free the memory back to the OS.I could force it to free by doing a swap with an empty std::vector.

1赞 Butuze 7/17/2019 #6

我猜你在 Linux 上。

如果确实需要最小化应用程序的内存占用,可以在清除映射后调用 malloc_trim()。我还建议看一眼 mallopt() 手册页 - 它有一些提示,说明为什么您的代码可以保留内存而不是将其返回给操作系统。

0赞 Hien Nguyen 9/30/2022 #7

Linux 编程接口的第 7.1.2 节清楚地解释了内存释放:

In general, free() doesn’t lower the program break, but instead adds the block of
memory to a list of free blocks that are recycled by future calls to malloc(). This is
done for several reasons:
- The block of memory being freed is typically somewhere in the middle of the
heap, rather than at the end, so that lowering the program break is not possible.
- It minimizes the number of sbrk() calls that the program must perform. (As
noted in Section 3.1, system calls have a small but significant overhead.)
- In many cases, lowering the break would not help programs that allocate large
amounts of memory, since they typically tend to hold on to allocated memory
or repeatedly release and reallocate memory, rather than release it all and then
continue to run for an extended period of time.