
Zeroing Memory is Hard: VC++ 2015 arrays - deverton
https://randomascii.wordpress.com/2016/07/17/zeroing-memory-is-hard-vc-2015-arrays/
======
brucedawson
Apparently gcc and clang are not fooled by { 0 }, so that's good:

[https://twitter.com/areuugee/status/754888773498867712](https://twitter.com/areuugee/status/754888773498867712)

~~~
Kristine1975
I'd wager they have an optimization pass that coalesces adjacent constant
stores.

~~~
AstralStorm
Among others. This is likely caught as zero initialisation already in the
front-end, before even GIMPLE/LLVM JIT is generated.

------
cleeus
At this point we must ask which Update of VS 2015 as MS just replaced the
Optimizer with an SSA based one.
[https://blogs.msdn.microsoft.com/vcblog/2016/05/04/new-
code-...](https://blogs.msdn.microsoft.com/vcblog/2016/05/04/new-code-
optimizer/)

~~~
gratilup
I'm the main developer of the new optimizer. It's a bit too much to say it
replaces the old one, it's more of an addition. I was aware of this issue with
initializing local arrays, it was on the TODO list - hopefully for the next
VS.

~~~
voltagex_
Are you allowed to respond directly to the author in this case?

~~~
apardoe-MSFT
There's not much preventing any engineer at Microsoft from talking to
developers. No lawyers need to be involved :-)

------
CamperBob2
Also note that you can't zero-initialize an array of objects that don't have a
default constructor, and that if you just add an empty default constructor to
shut the compiler up, the memory occupied by your array will not be
initialized to zero or anything else.

Seems obvious and elementary enough, but it got me good the other day.

~~~
AndrewGaspar
If you need to manually define a default constructor, and you want the
behavior of default-initializing all members, declare the constructor as:

    
    
        T() = default;

~~~
typelist
Explicitly defaulting the constructor behaves the same as an empty
constructor: all members are default-initialized. The problem is usually that
'default-initializing' doesn't zero out primitive (POD) types, but leaves them
uninitialized.

~~~
gpderetta
Explicitly using the T(), T{}, T = {} syntax will value-initialize the object,
which will zero-initialize trivially constructible types.

~~~
typelist
Ah, interesting. Apparently this is true even if some constructors are
explicitly '= default' (for the T x{} and T x={} list/aggregate initialization
cases only).

But I believe that rule doesn't apply for any objects where adding an '=
default' constructor would be useful, because it requires that there be no
user-defined constructors or private/protected members. Otherwise that syntax
ultimately calls the default constructor, which won't do any zeroing.

See
[http://en.cppreference.com/w/cpp/language/aggregate_initiali...](http://en.cppreference.com/w/cpp/language/aggregate_initialization)

------
userbinator
If you ask the compiler to optimise for size you should really be getting a
REP STOS for anything that needs more than the ~3 instructions which that
takes.

(It's not the fastest way for small sizes --- it actually is for larger sizes,
just like REP MOVS --- but the user asked for smaller, not faster code.)

------
apardoe-MSFT
Bruce, thanks for the kick! Six years is a long time to wait for a bug
resolution.

It turns out that our compiler has a minimum size limit in a memset
optimization. I’m sure the size limit was there for a Very Good Reason (TM) at
one point in time, but we are investigating whether we can remove it. Step one
is understanding why it was there in the first place.

------
kazinator
= { 0 } is an "initialize almost anything" idiom in C; it's worth recognizing
specially in a compiler.

------
someguydave
Far worse is trying to grow a std::vector with a std::vector.resize() and
subsequently trying to opt out of array intialization.

~~~
lorenzhs
Most STL containers with the default allocator will always initialise memory
(some, like std::array, don't iirc). That's a feature. If you don't want it,
then you'll have to use your own allocator or container. Both bring changes
throughout the codebase, unfortunately.

~~~
TillE
> Both bring changes throughout the codebase, unfortunately.

That's where auto often helps. Lets you change types as long as you don't
break the interface.

