为什么 VS Debug build 分配的变量相隔这么远?

Why does VS Debug build allocates variables so far apart?

我正在使用 Visual Studio 2019,我注意到在调试版本中,分配的变量彼此相距很远。我查看了 Project Properties 并尝试在线搜索但找不到任何内容。我在 Debug 和 Release 模式下 运行 下面的代码,这里是各自的输出。

int main() {
        int a = 3;
        int b = 5;
        int c = 8;
        int d[5] = { 10,10,10,10,10 };
        int e = 14;

        std::cout << "a: " << &a 
                << "\nb: " << &b
                << "\nc: " << &c 
                << "\nd_start: " << &d[0]
                << "\nd_end: "   << &d[4] + 1
                << "\ne: " << &e 
            << std::endl;
}

正如您在下面看到的,变量按照您的预期分配(一个接一个),中间没有浪费内存。甚至最后一个变量 e 也被优化为插入 c 和 d 之间。

// Release_x64 Build Ouput
a:          0000003893EFFC40
b:          0000003893EFFC44
c:          0000003893EFFC48
d_start:    0000003893EFFC50
d_end:      0000003893EFFC64
e:          0000003893EFFC4C    // e is optimized in between c and d

下面是让我感到困惑的输出。在这里你可以看到 ab 被分配了 32 个字节!所以它们之间有28字节的wasted/uninitialized内存。除了 int d[5] 之外的其他变量也会发生同样的事情。 dc 之后有 32 个未初始化字节,但在 e 之前只有 24 个未初始化字节。

// Debug_x64 Build Output
a:          00000086D7EFF3F4
b:          00000086D7EFF414
c:          00000086D7EFF434
d_start:    00000086D7EFF458
d_end:      00000086D7EFF46C
e:          00000086D7EFF484

我的问题是为什么会这样?为什么 MSVC 将这些变量分配得如此之远,什么决定了将它们分开多少 space 以便数组不同?

调试版本分配存储的方式与发布版本不同。特别是debug版本在每个存储块的开始和结束分配了一些space,所以它的分配模式有些不同

调试分配器还会检查它分配的块开始和结束处的存储,看它是否以任何方式损坏。

存储以量化块的形式分配,其中量程未指定,但大约为 16 或 32 字节。因此,如果您分配了一个包含六个元素的 DWORD 数组(大小 = 6 * sizeof(DWORD) 字节 = 24 字节),那么分配器实际上将传送 32 个字节(一个 32 字节量程或两个 16 字节量程)。因此,如果您写入元素 [6](第七个元素),则会覆盖一些 "dead space",并且不会检测到错误。但是在release版本中,quantum可能是8字节,会分配三个8字节的quanta,写入数组的[6]元素会覆盖属于下一个chunk的存储分配器数据结构的一部分。在那之后一切都是下坡路。在程序退出之前,错误甚至可能不会出现!您可以为任何大小的量程构造类似的 "boundary condition" 情况。因为分配器的两个版本的量程大小相同,但分配器的调试版本为自己的目的添加了隐藏 space,你将在调试和释放模式下获得不同的存储分配模式。