Zeroing Memory is Hard: VC++ 2015 arrays
randomascii.wordpress.com
randomascii.wordpress.com
> I recently noticed that it’s still an issue in VC++ 2015 Update 3
I hope the Python script is helpful for finding some of the odd variants that currently exist.
Seems obvious and elementary enough, but it got me good the other day.
T() = default;Exactly, that's what hosed me. Some double-precision floats ended up with garbage values and I couldn't see how it was happening.
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...
template<typename T> struct Function {
Function() = default;
void* callback = nullptr;
};
struct CPU {
Function<void ()> functions[65536]; //= {0} makes no difference
};
int main() {
CPU cpu;
return 0;
}
There's a bug in GCC, at least versions 5.1 - 5.4, where the above code will take 30s-90s to compile (depends on your CPU speed), and eat 500MB+ of RAM in doing it. But the bug isn't in 4.9, and possibly newer GCC releases.What causes it? "Function() = default;" of course. Change it to "Function() {}" and the code compiles in 100ms.
So because I can't tell people, "don't use GCC 5.x", or "don't ever use any of my class objects in a large array", I basically can't use "= default;" syntax on my constructors in any of my library code now :(
(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.)
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.
I hit this in a game server where a few percent of CPU time (that was enough to count as low-hanging-fruit) was being spent on memset inside of resize().
I have not solved it yet. The best solution - don't use std::vector for anything critical.
You can use it with std::unique_ptr<> to simplify memory management.
That's where auto often helps. Lets you change types as long as you don't break the interface.