【发布时间】:2020-09-13 23:16:36
【问题描述】:
一个相当简单的问题。但是,我在 VS2019 中得到了令人困惑的结果。因此,我设计了一些测试来确定发生了什么,但不确定结果如何。
问题: 分配的向量内存大约是向量预期大小的 1.5 倍。内存配置文件表明未解决的分配大约等于我看到的额外值。
我的试炼-
- 包含 char、float 和 int 的简单结构。分配的值接近计算值。
- 将 40 个整数的向量添加到结构并检查分配。
- 使用 2 个这样的向量而不是 1 个
- 现在使用 6!
- 使用 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。
- Memory comparison- no vector, 1 vector
- Memory comparison- 1 vector, 2 vectors
- Memory comparison- insufficiently reserved vector
编辑: - 内存分配和代码的细分。有趣的是,我得到的数字保持不变。
【问题讨论】:
-
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。