简体   繁体   中英

Operator new behaves differently in Debug mode than in Release mode in MSVC

While testing some things regarding page faults I discovered a curious difference between how new operates in Debug mode and Release mode in MSVC. Consider the following code 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';
}

The code allocates a million normal memory pages on most architectures. It then physically writes to this allocated memory, so the memory really has to be "given" 2 to the program - not merely "reserved" for it in some way. The curious thing is, when this actually happens. To investigate this, I stepped through the code using the Visual Studio debugger and looked at the memory usage graph in Task Manager. The results are below:

测量结果

The red time point is the program being launched, the green time point/interval is the call to new char[] , the blue time point/interval is the for loop.

As it turns out, in Debug mode, new both "reserves" and "gives" memory to the program. Meanwhile, in Release mode, it only "reserves" it, as the memory is "given" by the loop. I expected only the behavior present in Release mode - I thought that the memory is "given" to the program only when a page fault occurs.

Why does new behave in this way? Does this have any significant implications?


1 By the way, for some reason changing auto* pages to auto* const pages causes an Internal Compiler Error.

2 I am a bit confused regarding the correct terminology, so I used "given" and "reserved" instead.

The debug builds do a lot of cool stuff for you to help you find bugs. One is writing a known value into the program's memory so you'll more easily recognize that you've messed around with uninitialized storage. This means the debug version of new acquires the memory and immediately uses it, forcing the system to find and hand over real memory in the green region rather than deferring that expensive task to when the program actually uses it in the blue region.

Debug new fills memory with recognizable pattern.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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