In the following C++ program I am examining how many bytes are zeroed in the uninitialized heap memory.
<code>#include <cstdio>
#include <string>
static void CountZerosNonZeros(size_t nBytes)
{
char* mem = new char[nBytes];
size_t count[2] = {};
for (size_t i = 0; i < nBytes; i++)
count[mem[i] == 0]++;
delete [] mem;
std::printf("Zeros: %7zun", count[true]);
std::printf("Non-zeros: %7zun", count[false]);
}
int main(int argc, char** argv)
{
const size_t nBytes = std::stoull(argv[1]);
CountZerosNonZeros(nBytes);
}
</code>
<code>#include <cstdio>
#include <string>
static void CountZerosNonZeros(size_t nBytes)
{
char* mem = new char[nBytes];
size_t count[2] = {};
for (size_t i = 0; i < nBytes; i++)
count[mem[i] == 0]++;
delete [] mem;
std::printf("Zeros: %7zun", count[true]);
std::printf("Non-zeros: %7zun", count[false]);
}
int main(int argc, char** argv)
{
const size_t nBytes = std::stoull(argv[1]);
CountZerosNonZeros(nBytes);
}
</code>
#include <cstdio>
#include <string>
static void CountZerosNonZeros(size_t nBytes)
{
char* mem = new char[nBytes];
size_t count[2] = {};
for (size_t i = 0; i < nBytes; i++)
count[mem[i] == 0]++;
delete [] mem;
std::printf("Zeros: %7zun", count[true]);
std::printf("Non-zeros: %7zun", count[false]);
}
int main(int argc, char** argv)
{
const size_t nBytes = std::stoull(argv[1]);
CountZerosNonZeros(nBytes);
}
I compiled this on Visual Studio 2022 v17.10.4 (cl.exe v19.40.33812) to x86-64 binary with optimizations. I found, that
- for
nBytes
<=1044472
some bytes are not zeroed, while - for
nBytes
>1044472
all are zeroed.
What makes this difference?
I couldn’t reproduce this on Godbolt, so this is probably an MSVC feature. Also, I am aware, that using uninitialized memory is UB. Still, I think the question is interesting.
12