繁体   English   中英

我如何确保在取消分配后将std :: vector分配的内存分配回操作系统?

[英]How can I make sure the std::vector allocated memory give back to operating system after deallocating?

下面的代码调用foo并使用while(1)监视内存使用情况。 据我所知,在“完成”打印之后,将var d释放,并且STL容器将自己释放数据空间(堆)。

#include <vector>
#include <string>
#include <iostream>

void foo() {
  std::vector<std::string> d(100000000);
  for(int i = 0; i < 100000000; ++i) d[i] = "1,1,3";
  d.resize(0);
  d.shrink_to_fit();
}

int main(int argc, char *argv[])
{
  foo();
  std::cout << "finished" << std::endl;
  while(1) {;}
  return 0; 
}

但是我观察到的(使用htop ):内存没有被释放回操作系统。 这只是一个基准,是与MESOS相关的实际代码,每个程序都有内存限制。

我已经尝试使用glibc 2.15在Linux服务器上使用g ++-4.7.2 g ++-4.8.1,clang ++等多种版本的编译器。 此外,我还使用tcmalloc代替了默认的malloc,但是它仍然不起作用(在MAC机器中,该问题不会发生)。

有什么问题? 如何确定内存还给OS? 谢谢。

如何确定内存还给OS?

您可以终止过程。

有什么问题?

可能没有一个。 程序不返回内存是很正常的(尽管Linux对于某些特别大的分配确实会提前返回内存)。 他们通常使用sbrk或等效命令来增加可用的虚拟地址空间,但是通常不值得尝试返回已释放的内存。 这可能是违反直觉的,但是在几十年中,它也已被证明可用于数百万个程序,因此,除非有具体的实际问题,否则您不应该为它烦恼。 它不会给您造成问题,因为当应用程序执行进一步的分配时,释放的内存将被重用,因此您提到的“每个进程的MESOS内存限制”仍然会以相同的方式影响最大瞬时内存使用量的“高水位”。

需要注意的是与操作系统的虚拟内存支持可换长期未使用重新分配的页到磁盘,以便为后盾RAM 可以由内核或其他应用程序重复使用。

也可以使用例如内存映射文件来对此进行手动控制,但是编写这样的分配器并使用from Standard容器是一项艰巨的任务……关于如何解决该问题,还有很多其他的SO问题。

从操作系统分配内存有两个缺点:

  1. 高开销。 系统调用涉及到进入保护模式的过程,该过程比简单的函数调用要花费更长的时间,因此,操作系统本身的内存管理可能非常复杂。
  2. 高粒度。 操作系统可能具有最小大小分配,例如4K。 6字节字符串的开销很大。

由于这些原因,C ++内存分配器只会向OS请求较大的块,然后在通过newmalloc请求时将其打包。

释放这些内存后,它们将被放回池中,以便在下一个请求时再次分发。 现在很有可能最终释放了更大块的所有块,但是在现实生活中多久发生一次? 很可能每个块至少有一个分配会持续很长时间,从而阻止将该块返回给OS。 如果返回它,你认为什么是程序会转身的机会,后来要求其重新短的时间? 实际上,通常无需支付将块返回操作系统的费用。 您的测试程序是一个高度人为的案例,不值得进行优化。

在大多数现代系统中,操作系统以页面形式管理内存。 应用程序内存由库功能在池(堆)中管理。 当您的应用程序分配内存时,库函数会尝试查找所需大小的可用块。 如果内存不在池中,则库将调用系统以将更多页面添加到进程中以合并到池(堆)中。 释放内存后,它会返回到池中。 池中分配的页面不会返回到操作系统。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM