Jump to content
  • Advertisement
Sign in to follow this  
Juliean

[MSVC] Why does SDL initialize member variables?

This topic is 816 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

 

so I've been wondering for a time whats up with microsofts SDL-checks. While the feature seems really helpfull for spotting some issues in your code, on the other hand it just flat out 0-initializes every member variable, see this:

 

 

  • Performs class member initialization. Automatically initializes all class members to zero on object instantiation (before the constructor runs). This helps prevent the use of uninitialized data associated with class members that the constructor does not explicitly initialize.

 

I've always been bothered by this. Why do that? In my personal experience, all this does is mask up errors like this:

class Foo
{
public:
	Foo(Bar* pBar)
	{
		// oups, I forgot to set m_pBar. 
	}
	
	void DoSomething(void)
	{
		// So without SDL, this function will most likely crash, indicating me that I forgot to set m_pBar
		// with SDL, it will just silenty do something completely different than I expected
		if(m_pBar)
			m_pBar->DoSomethingElse();
	}
		
private:
	Bar* m_pBar;
}

This is kind of a contrived example but really I had this stuff happen to me more than once in my own code.

 

Also another problem is that while sometimes I might just forget to set a pointer rightfully to "nullptr" in an empty ctor, the program will run happily ever after in debug mode, but when I compile in shipping mode, where SDL is deactived, I often get random crashes due to now uninitialized pointers (which thankfully are easy to track down using static code analysis, but still)...

 

So I've been wondering:

 

- Is there any merit to SDL actually null-initializating member variables for safely, or am I correct in my notion that this actually leads wrong/more insecure code.

- (Out of interest) Do you even have SDL on? If so, do you have it for all your builds (including shipping), or do you deactivate it for efficency reasons in release/shipping builds?

Share this post


Link to post
Share on other sites
Advertisement
Well, if you have such an error than it's safer to have it on nullptr than some random value. The random value might be one you are allowed to access. nullptr reliably crashes.

Share this post


Link to post
Share on other sites

When /sdl is enabled, the compiler generates code to perform these checks at run time:
*Performs class member initialization

This seems vague -- does it check for uninitialized members, or zero them, or both? If it generates a breakpoint when a debugger is attached, but also zero-fills if no debugger is attached, then it's arguably helpful -- helps find the bug and mitigates its harm in the wild.
But yes, generally it's better for your compiler/runtime to initialize members to something like 0xcdcdcdcd by default, as that's likely to cause your code to crash, which lets you find the bug.

I can imagine that when inheriting an old, unmaintainable, buggy codebase, it might be very tempting to have a "zero-initialize all memory by default" compiler switch! :D

Share this post


Link to post
Share on other sites
Well, if you have such an error than it's safer to have it on nullptr than some random value. The random value might be one you are allowed to access. nullptr reliably crashes.

 

True, for the case where the pointer might never be null anyways its safer, but in the case where nullptr is an legit value like in my example, it can lead to bugs that otherwise would not occur. Especially if its off for shipping builds, which I always asumed is normal with SDL.

 

This seems vague -- does it check for uninitialized members, or zero them, or both? If it generates a breakpoint when a debugger is attached, but also zero-fills if no debugger is attached, then it's arguably helpful -- helps find the bug and mitigates its harm in the wild.

 

Well further in on they say that it zero-fills the values before running the constructor, so it will probably just fill the entire memory-range of the class with 0s. Thus it doesn't produce a breakpoint in debugger but really just simply masks away all your unitialized pointers, integers, etc... as if you set them to 0 yourself.

 

But yes, generally it's better for your compiler/runtime to initialize members to something like 0xcdcdcdcd by default, as that's likely to cause your code to crash, which lets you find the bug.

 

Well that would actually be useful as it won't just do some random stuff with the unitialized pointer while also showing the crash. I'm pretty sure there is a compiler switch or something that does that, so the zeroing out really mystifies me even more.

Share this post


Link to post
Share on other sites

It's been a while since I dug into the subtleties of the Windows virtual memory APIs, but carving off a page and VirtualProtecting it with PAGE_NOACCESS would satisfy the non-NULL requirement, but also point at invalid, but not potentially arbitrary, memory.  Of course, it's typically the case where if something like that isn't done, there's normally a perfectly good reason which we're just not currently aware of.

Edited by mhagain

Share this post


Link to post
Share on other sites

I think you're missing the point that the "S" in "SDL" stands for "Security".

 

It's nothing to do with assisting debugging, it's nothing to do with spotting non-security issues in your code.

 

So in the case of a pointer it's either initialized or it's not, and if it's not initialized then it's going to be pointing at some memory address that's effectively random.  Hence security: a 3rd party could use your unitialized pointer to gain access to some other arbitrary data in your process address space.

 

Truth be told I really didn't get that security means this kind of security, lol. I just thought security mean that it makes the programm less prone to crashing, but seeing how it also incorporates the /GS switch (for protecting against buffer overruns) it makes perfect sense.

 

So seems that is my answer right there. Seems that in this case you will obviously want to have SDL turned on all the time in all builds, because there is no point just protecting your developement/debug build. In this case I think I'll just turn it off altogether, as of now I don't require the additional security (I dare you to hack my offline games :D ) and I certainly don't want the overhead of additional checks for things that I could have easily found using something like cppcheck.

Edited by Juliean

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!