【问题标题】:Explosion of memory using std::map使用 std::map 的内存爆炸
【发布时间】:2016-04-19 20:46:59
【问题描述】:

在 VS10 的 C++ 中使用 std::map 时遇到问题。 当我运行这个简单的代码时

std::map<int,int>myMap;
for(size_t i=0;i<1000000;i++){
     myMap[i]=i;
}

我的记忆爆炸到 256Mo,这对我来说似乎很奇怪。 如果我使用

std::vector<int>myVector(1000000);

我得到了预测的 4Mo。

如果有人能解释这种现象。 谢谢

【问题讨论】:

  • 这是在开玩笑吗?你知道 std::map 和 std::vector 实现的区别吧?
  • 节点大小可能是 (parentptr, leftptr, rightptr, color, key, value),所以每个 ~8+8+8+1+padding+4+4+padding=40bytes。为 Windows 中的分配开销添加约 24 个字节会导致每个节点总共有约 64 个字节,x1000000 = 61Mb。嗯。对于未使用的页面分配,我只希望看到大约 4Mb。不确定其他 200Mb 来自哪里。
  • 您确定它是 256 Mb,而不是 25.6?对于一百万个节点的映射,我预计会略低于 24 Mb,即值 4,节点 4,左右指针 8+8。
  • 你如何测量内存使用情况?

标签: c++ visual-studio-2010 dictionary memory stl


【解决方案1】:

std::map 很可能实现为红黑树,这意味着以下字段,假设 x64:

  1. 红色或黑色(1 个布尔值,但由于填充,实际上是 4 个字节)
  2. 父(8 字节指针)
  3. 左孩子,右孩子(两个 8 字节指针)
  4. 根对象(8 字节指针)
  5. 数据密钥(4 个字节为 int)
  6. 数据值(4 字节为 int)

这可以让您每个项目最多 44 字节或 44 兆字节的内存。与std::vector 的情况不同,它们中的每一个都是独立的对象,它添加了大约 24 个字节的附加数据。这使我们达到了 68 兆字节。这仍然是您所看到的四分之一,但至少您可以看到为什么大小差异很大。

【讨论】:

  • 我使用 Visual Studio 2015 运行了一个测试,运行 OP 提供的确切代码使用了大约 45MB 内存(从基线的 ~4MB 到对象存在时的 49MB,然后又回到对象被破坏时为 4MB)。我怀疑它正在优化对象分配,因为这基本上只是将它放在对象本身使用的原始内存之上,而忽略了您和另一个用户确定的“分配开销”。
  • @Xirema:我尽力强调,我列出了我认为不一定准确的“最坏的可能”数字,只是显示了可能的高数字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-12
  • 1970-01-01
  • 2021-12-09
  • 2020-11-23
  • 2019-07-26
  • 2020-04-12
  • 2011-01-31
相关资源
最近更新 更多