首页 > 解决方案 > 为什么 VS Debug 构建分配变量如此之远?

问题描述

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

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

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

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

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

标签: c++visual-studiomemoryvisual-c++allocation

解决方案


调试版本分配存储的方式与发布版本不同。特别是调试版本在每个存储块的开头和结尾分配了一些空间,因此它的分配模式有些不同。

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

存储是按量化的块分配的,其中未指定量子,但大约是 16 或 32 字节。因此,如果您分配了一个包含六个元素的 DWORD 数组(大小 = 6 * sizeof(DWORD) 字节 = 24 字节),那么分配器实际上将传递 32 个字节(一个 32 字节的量程或两个 16 字节的量程)。因此,如果您编写元素 [6](第七个元素),则会覆盖一些“死区”并且不会检测到错误。但是在发布版本中,quanta 可能是 8 字节,会分配三个 8 字节的 quanta,写入数组的 [6] 元素会覆盖属于下一个块的存储分配器数据结构的一部分。在那之后,一切都是下坡路。在程序退出之前,甚至可能不会出现错误!您可以为任何大小的量子构建类似的“边界条件”情况。


推荐阅读