Minimum example:
#include <fstream>
struct TFoo
{
bool Field1_ = false;
uint64_t Field2_ = 0;
};
int main() {
TFoo Foo_{};
const char* filename = "text.txt";
std::ofstream f(filename);
f.write((char*)(&Foo_), sizeof(Foo_));
}
clang since 5th version in msan reports something like this:
Uninitialized bytes in __interceptor_fwrite at offset 0 inside [0x720000000000, 15)
==71928==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x2823aa (/home/<hidden>/test-ofstream+0x2823aa)
#1 0x27830f (/home/<hidden>/test-ofstream+0x27830f)
#2 0x272757 (/home/<hidden>/test-ofstream+0x272757)
#3 0x271388 (/home/<hidden>/test-ofstream+0x271388)
#4 0x270c96 (/home/<hidden>/test-ofstream+0x270c96)
#5 0x2709e2 (/home/<hidden>/test-ofstream+0x2709e2)
#6 0x26ff9e (/home/<hidden>/test-ofstream+0x26ff9e)
#7 0x7fbc7238382f (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
It is because padding bytes between Field1_
and Field2_
are not initialized.
It is ok, MSAN is right.
But if the code contains very large examples of such code (saving structs to binary files), is there any beautiful method to massively make the code better?
(Packed structs is not a solution for us.)
If you can change the definition of
struct TFoo
, you can add a constructor like this:I think you cannot use
memset
this way according to the standard, but it may work with your compiler. See How can I zero just the padding bytes of a class?, where this solution is discussed.ORIGINAL ANSWER
This came to my mind to zero out padded bytes between
Field1_
andField2_
. But honestly, I am not sure if it is Standard compliant. Definitely, some kind of serialization ofTFoo
objects would be much better, but if I understood correctly, it's not an option for you, is it?UPDATE
From http://en.cppreference.com/w/cpp/language/union: At most one variant member can have a default member initializer. The above code is therefore likely not correct. But you can, e.g., define default constructor for
TFooWrapper
to zero out all bytes.