繁体   English   中英

在 MSVC 中,操作员 new 在调试模式下的行为与在发布模式下的行为不同

[英]Operator new behaves differently in Debug mode than in Release mode in MSVC

在测试有关页面错误的一些事情时,我发现new在 MSVC 中的调试模式和发布模式下的运行方式之间存在奇怪的差异。 考虑以下代码1

#include <array>

constexpr size_t PAGE_SIZE = 4096;

int main()
{
    const size_t count = 1000000;
    char* const mem = new char[PAGE_SIZE * count];

    // page align the pointer, c-style casts used for brevity
    auto* pages = (std::array<char, PAGE_SIZE>*)((size_t)mem - (size_t)mem % PAGE_SIZE + PAGE_SIZE);
    
    for (int i = 0; i < count; ++i)
        pages[i][0] = 'a';
}

该代码在大多数架构上分配了一百万个正常的 memory 然后它物理地写入这个分配的 memory,因此 memory 确实必须“给予”程序2 - 而不仅仅是以某种方式为它“保留”。 奇怪的是,当这真的发生时。 为了对此进行调查,我使用 Visual Studio 调试器逐步完成了代码,并查看了任务管理器中的 memory 使用图。 结果如下:

测量结果

红色时间点是正在启动的程序,绿色时间点/时间间隔是对new char[]的调用,蓝色时间点/时间间隔是for循环。

事实证明,在调试模式下, new的“保留”和“给予”memory 给程序。 同时,在发布模式下,它只“保留”它,因为 memory 是由循环“给定”的。 我只期望发布模式中存在的行为 - 我认为 memory 仅在发生页面错误时才“给予”程序。

为什么new会这样? 这有什么重大影响吗?


1顺便说一句,由于某种原因,将auto* pages更改为auto* const pages会导致内部编译器错误。

2我对正确的术语有点困惑,所以我改用了“given”和“reserved”。

调试版本为您做了很多很酷的事情来帮助您找到错误。 一种是将已知值写入程序的 memory 中,这样您将更容易识别出您已经搞砸了未初始化的存储。 这意味着new的调试版本获取 memory 并立即使用它,从而迫使系统在绿色区域中找到并移交真正的 memory,而不是将这项昂贵的任务推迟到程序在蓝色区域中实际使用它时。

用可识别的模式调试new填充 memory。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM