为什么内存没有在top和pmap中释放?

时间:2015-09-02 02:42:41

标签: c++ dictionary memory free pmap

我用valgrind检查代码,没有内存泄漏。 但我使用的是顶级'要查看内存,在删除'之后会花费295MB内存。调用。
我使用' pmap -x'通过[anon]来查看内存,大部分内存成本:

Address           Kbytes     RSS   Dirty Mode   Mapping
0000000001114000  301672  301588  301588 rw---    [ anon ]

我不知道为什么记忆已被释放,但它的成本仍为295MB。谁知道为什么?

#include <map>
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
void test8() {
  map<string, map<string,string>* > m;
  for (int i = 1; i < 10000; i++) {
    map<string, string>* p = new map<string, string>();
    for (int j = 1; j < 100; j++) {
      (*p)[string(j,'a')] = string(j,'a');
    }
    m[string(i,'a')] = p;
  }

  map<string, map<string,string>* >::iterator it;
  for (it = m.begin(); it != m.end(); it++) {
    it->second->clear();
    delete it->second;
  }
  m.clear();
  cout << "free done" << endl;
}
int main(int argc, char**argv) {
  test8();
  getchar();
}

3 个答案:

答案 0 :(得分:0)

您正在使用的工具是监视进程从操作系统分配的内存,它们不监视C ++程序中当前活动的内存分配的大小。

当您使用C ++代码分配内存时,可能需要转到操作系统并要求更多内容。这将增加您正在监控的值。

但是,当你释放它时,没有要求将内存返回提供给操作系统,因为它很快就会再次需要它。

因此,即使您的C ++程序已经释放了内存,C ++ 环境也会保留它,以防您再次需要它。

答案 1 :(得分:0)

这是特定于操作系统的,但通常一旦进程抓住内存就会保留它。您可能没有使用内存,但它可用于您的进程(在空闲池中)。

答案 2 :(得分:0)

缓存,缓存,缓存。哦,是的,和碎片。

通过不同的层分配内存。如果您的应用程序分配内存,它将询问它到C / C ++运行时。 C / C ++运行时将检查自己的数据结构是否有可用内存,如果它没有,它会将调用转发给操作系统。根据C / C ++运行时(和版本),C / C ++运行时数据结构可能很广泛,或者C / C ++运行时可能只是直接将调用转发给OS。对于Microsoft Visual Studio(此刻不使用Linux,抱歉),我知道:

  • 旧版本在C / C ++运行时中具有相当广泛的内存数据结构
  • 较新的版本似乎始终将调用转发到操作系统(Windows堆)

这意味着当释放内存时,C / C ++运行时可能决定保留内存(出于多种原因,包括如果您决定再次分配内存则能够更快地返回内存),或者可能将其返回到操作系统(如果它已经有很多空闲内存)。操作系统可能完全相同:保留内存,以备再次分配,或将其标记为已立即解除分配。

哦,是的,碎片化。 内存通常分为页面。在Intel x86和amd64上,页面为4KB。每个页面都包含一些信息,包括:

  • 保护权限(只读,读写,执行(参见DEP,NoX位)
  • 其实际位置(物理内存,分页到页面文件,......)

假设您的应用程序分配16次256字节,并且您很幸运,所有这些内存都分配在一页4KB内。如果您现在释放其中的15个分配,则第16个分配将保留分配的内存页,从而阻止操作系统将其标记为已释放。编写一个分配1.5GB的应用程序,然后释放1.4GB的内存,并且仍然消耗1.5GB的内存(根据操作系统),这很容易。

这意味着即使您释放了所有内存,也可能只有一些内部C / C ++运行时数据结构,或者某些第三方数据结构(可能是某些缓存)可能会保留一些页面,尽管您完全取消了所有内容你的记忆。