【问题标题】:Memory usage in a vector of struct结构向量中的内存使用情况
【发布时间】:2020-09-13 23:16:36
【问题描述】:

一个相当简单的问题。但是,我在 VS2019 中得到了令人困惑的结果。因此,我设计了一些测试来确定发生了什么,但不确定结果如何。

问题: 分配的向量内存大约是向量预期大小的 1.5 倍。内存配置文件表明未解决的分配大约等于我看到的额外值。

我的试炼-

  1. 包含 char、float 和 int 的简单结构。分配的值接近计算值。
  2. 将 40 个整数的向量添加到结构并检查分配。
  3. 使用 2 个这样的向量而不是 1 个
  4. 现在使用 6!
  5. 使用 2 个向量,但不要保留向量的整个大小
#include <vector>
struct wow
{
    char a;
    int glint;
    int b;
    std::vector<int> length = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    wow(char k, int g, long c)
    {
        a = k;
        glint = g;
        b = c;
    }
};
int main()
{
    std::vector<wow> tr;
    tr.reserve(180000);
    for (int i = 0; i < 180000; ++i)
        tr.emplace_back('g', 23, 6345345);
}

在试验 2、3 和 4 中,分配/使用的内存大约是计算值的 1.5 倍!尽管在向量中保留了所需数量的元素,但这仍然存在。堆内存分配或多或少与任务管理器中使用的内存匹配。鉴于我能够匹配第一种情况的内存分配,因此可以合理地假设它们在其他情况下也会匹配。

最初,我假设 sizeof 运算符无法确定向量的大小导致重复重新分配,但事实并非如此。内存曲线呈线性上升,没有重新分配典型的短期波动(第 5 次试验)。 breakdown of memory allocation 显示在链接中。它表示在 42MB(总计)中,35MB 用于赋值运算符,7MB 用于分配向量。这对我来说毫无意义。有人可以澄清一下吗?

内存分配供参考。四个试验的预期(计算)值为 2.05MB、29.52MB、57.0MB 和 166.8MB。实际分配(按 VS2019)为 2.58MB、46.53MB、82.4MB 和 266.25MB。

编辑: - 内存分配和代码的细分。有趣的是,我得到的数字保持不变。

【问题讨论】:

  • sizeof wow 在您的编译中显示了什么,您的预期值基于什么?
  • sizeof(wow) 无向量返回 12B,1 为 28B,2 为 44B,6 个向量为 108B。预期值基于我要使用的向量的大小,即 40 个整数 * 4B * #vectors + 12(对于 2 个整数和字符)。现在我想了想,你提出了一个有效的问题。因此,我通过编辑代码重新进行了这些测试。这一次,我直接定义了要在结构中使用的向量,并避免对其进行更新。编辑内存分配细目。请注意,所有数字都保持不变。
  • 您的估计看起来仍然有点乐观。对于 char + 2 ints + 2 个向量 sizeof wow 是 44,所有分配的理论最小值将是 180K * (44 + 2 * 40 * 4) 或大约。 62.5 MB 与您引用的 57 MB。并且假设除了元素的实际大小(标准不保证,因此您必须查看您正在使用的特定实现)之外,非空向量的向量存储没有开销。快速检查是用 malloc 的指针替换向量并比较内存占用。
  • 有趣!我得到的印象是 sizeof 返回没有向量的结构的大小。这就是你使用 44 + 2 * 40 * 2 而不是 12 + 2 * 40 * 2 的原因吗?如果是真的,你能猜出 44 的细分吗?
  • 在这里感到困惑。 sizeof 会给你vector 的大小,但不能告诉你向量指向的大小。 vector 通常是 3 个指针,大小为 12 或 24 字节。 char 将被填充以对齐随后的 int,然后是另一个 int。让我们假设 32 位 int,所以要么是 24 字节,要么是 40 字节,因为 vector 必须是 64 位对齐的。我不希望 wow 有 28 或 44 个 vector

标签: c++ memory vector struct


【解决方案1】:

感谢@dxiv,我能够匹配测试用例中的内存使用情况。我在这里添加一个答案作为参考。

主要问题是我使用的是调试模式而不是发布模式。更改此设置会使分配的内存减少近 20%,从而确定实际分配的内存。

不匹配的另一部分来自我对向量大小的错误估计。 STL 是动态数据结构,它从堆中为添加的每个元素分配内存。一个向量至少由三个指针定义,一个指向起点,一个指向终点,一个指向向量的容量。我也错过了这个 12B 的分配。

【讨论】: