c++ - 为什么 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 将这些变量分配得如此之远,以及是什么决定了将它们分开的空间,以便数组不同?
解决方案
调试版本分配存储的方式与发布版本不同。特别是调试版本在每个存储块的开头和结尾分配了一些空间,因此它的分配模式有些不同。
调试分配器还检查它分配的块的开始和结束处的存储,以查看它是否以任何方式损坏。
存储是按量化的块分配的,其中未指定量子,但大约是 16 或 32 字节。因此,如果您分配了一个包含六个元素的 DWORD 数组(大小 = 6 * sizeof(DWORD) 字节 = 24 字节),那么分配器实际上将传递 32 个字节(一个 32 字节的量程或两个 16 字节的量程)。因此,如果您编写元素 [6](第七个元素),则会覆盖一些“死区”并且不会检测到错误。但是在发布版本中,quanta 可能是 8 字节,会分配三个 8 字节的 quanta,写入数组的 [6] 元素会覆盖属于下一个块的存储分配器数据结构的一部分。在那之后,一切都是下坡路。在程序退出之前,甚至可能不会出现错误!您可以为任何大小的量子构建类似的“边界条件”情况。
推荐阅读
- paypal - Paypal 订阅用户:50% 的时间显示“我们无法处理您的定期付款”
- sql - 当值更改时重置行号
- javascript - 为什么 npm run 会导致错误:“Router.use() 需要一个中间件函数,但需要一个 ' + gettype(fn)”?
- python - FastAI NLP 迁移学习,迁移学习模型是否具有预训练模型的词汇?
- flutter - 如何使用键组合两个嵌套映射的子集?
- string - 试图在 KMP 算法中获取模式的前缀表
- c - 如何从另一个可执行文件调用二进制文件的_start?
- html - Angular:我想为登录用户创建一个隐藏和显示选项以隐藏和显示他们的帐户详细信息
- javascript - 无法在 Bootstrap 5 中使用 JavaScript 打开 Modal
- azure - Azure 函数 proxies.json 文件未生效