Class/struct members not initialized, makes initialization different between Windows and OSX/Linux

Hi there,

I noticed that many structures are not inititialised hence generating warnings in Windows that does not zero them up as I believe it is the case in OSX/LLVM and also GCC linux compilers?

Windows suggest to always set them (i.e. scalar int value could be zeros, float/double could be NANs…).
The warning message is:
C26495: Variable ‘%variable%’ is uninitialized. Always initialize a member variable (type.6)

This results in a lot of warnings and I think possible different behaviors in windows versus OSX/Linux, this can easily be fixed too.

Also g-mon found out this problem in:

I think this is mainly because windows does not allocate zero filled memory buffers, there could be garbage in allocated memory causing trouble in Windows when it would work in other systems.
There are also intellisense related warnings, but these could be adressed as they really happen in the code.

Can you tell me where the warnings are being thrown up?
Also, what compiler version are you using that is showing them?

We build Waveform and all the example projects constantly and have werror on so I would have thought this would fail builds if these errors were present. Maybe this is a new or optional warning we don’t have enabled?

But the other half to this is are you sure those structs/classes are being used uninitialised? That’s a very different situation to them being declared but not initialised.
I run with Clang’s UBSan and run the static analyser on CI, these are usually pretty good at picking up errors like this.

Basically I need to replicate the warnings/errors before being able to fix them.

These warnings are coming from CppCoreCheck, one of the static analysis tools of Visual Studio. They are not compiler warnings.

Ok, so these check the “Core Guidelines” which are a series of best practices rules rather than actual sources of errors.

I’ve not got this installed yet so can’t really comment on how much work it will be to fix them and therefore how high priority this is.

At the moment, I’m really focusing on getting Tracktion Graph completed, tested and shipped and also working on my ADC talk.

But they are still real in the sense that there are plenty of unitialized by default struct as an example (these one are easy to check as they have no code to further analyze to see if if their data members are initialized in the end or not.
Then we need to trust that the caller code always initialize them before use or it could lead to potential problems, except if the data member is not used.
@dave96 I can find precise examples of them when building with vs2019, I think Roland in the thread I attached to the discussion also hit them, I’m sure you can see them if you look at the “error” bottom panel instead of the output.

Usually I ignore them, but for initialization cases I’m always more worried as like I said, I remember I had trouble a while ago with Windows (not zero’ing the allocated data it provides hence the compiler warning I suppose).

It does not necessarily means there is a problem in this code (most of the time there is none as the calling code does set these variables before use, but not always).

As discussed, I don’t think there is any urgent need for you to dig into that recurrent problem (that hopefully most of the time is going to be a false positive) but because you asked and for the sake of more precise understanding of what we actually observed that you could not reproduce (220+ warnings but only when opening particular source that the intellisense engine tries to ‘lint’) :

Ok I’ll take a look at these when I get a chance but I think it’s important to understand what you’re asking as you’ll get different replies on this depending on who you ask.

This isn’t a Windows thing, in general C++ compilers don’t zero-initialise memory, this would incur a non-zero cost and C++ has the philosophy of “don’t pay for what you don’t use”. There is no way around this. I can imagine many performance code bases that wouldn’t want to zero-initialise their objects because they don’t want to pay this cost. They will rely on well formed code, static analysers and run-time sanitisers to check if any uninitialised objects/members are used.

You may not always see this because some compilers zero out memory in debug modes or fill them with a specific bit pattern so they can be caught at run time (e.g. CDCDCDCD).

Running a tool that has an option to check for uninitialised members is not the same as ill-formed code. It’s more a “best practice for the safest code” if that’s what you’re prioritising over performance.

For us, in almost all situations we’d take this best practices approach but that might not always be the case if we have data that not zeroing structs has a noticeable performance hit.

Next time I’m in VS2019 I’ll see what is reported there and if there are places we can tidy up these warnings.

I noted that mostly on windows msvc compilers as opposed to osx llvm and linux gcc compilers.

You can since (C++11? or was it C++14?) a while now initialise directly the member variable e.g.:

int paramID=0;

Would address the intellisense concern, but like you said ; it has a cost.
But then maybe we could disable this intellisense warning by a pragma with a comment explaining that we know about that and it’s a compromise for performance we are willing to take?

Thanks for looking at this, it is quite of a nuisance when building, but I think I may end-up disabling the full intellisense warnings and save you some time there as I’m convinced that most of the time it is not a real problem :slight_smile:

Yeah, we know about in-place member initialisation, it’s used all over the codebase and yes, we’ll probably update most of these warnings when we get a chance it’s just a tricky time to do so at the moment (and I haven’t even seen how many places it would be, most of what your screenshot shows is juce code).

I also don’t know if we’re able to silence the warnings easily. If I understand correctly they require [[gsl::]] attributes to be added and I think the presence of those will issue warnings in a C++14 complier (https://en.cppreference.com/w/cpp/language/attributes - All attributes unknown to an implementation are ignored without causing an error)

If this was a real MSVC compiler warning it would have hit our CI and would have been fixed but because it’s a tool we don’t currently have CI implemented for it’s going unnoticed and will require a bit of work to fix. Maybe ask me again after ADC as we’ll have a bit more time then.

So I got around to doing the analysis with CppCoreCheck and have fixed the uninitialised variable issues.

However, CppCoreCheck is very dogmatic in some of the issues it flags. There are lots of “prefer scoped enum” warnings which whilst I agree with, we have in the code base because a large portion of it was written before C++11 was around. I’m struggling to go through and break dozens of places in the API for essentially no reason so these will have to stay for now and I’ll replace them over time.

I should note that there are similar warnings flagged in JUCE and the internal libs it comes with (flac etc.) which will be harder to get rid of.

1 Like