Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Dark GDK / What could cause this crash?

Author
Message
Hawkblood
14
Years of Service
User Offline
Joined: 5th Dec 2009
Location:
Posted: 30th Jun 2011 04:34
First I have to say the program I am refering to is very large and I will not be posting the code in it's entirety. The game compiles and runs without errors (that I can tell). The problem occurs when I exit the game. I unload all my loaded/created resources:

The GUI.UnloadMenuGUI(); is:



This error ONLY occurs when running the "Release" version and NEVER happens when running the "Debug" version. Also, it doesn't ALLWAYS occur in the release, but when it does, it happens each time I exit.... Makes sense?

Any thoughts?

The fastest code is the code never written.
Matty H
16
Years of Service
User Offline
Joined: 7th Oct 2008
Location: England
Posted: 30th Jun 2011 19:25
I had a similar problem once, debug worked and release never. It turned out to be a fence post error, a 'for' loop was going too far.

Can't remember why but debug mode can sometimes let these kinds of errors go

It may not be the same but thought I would mention.

JTK
14
Years of Service
User Offline
Joined: 10th Feb 2010
Location:
Posted: 30th Jun 2011 21:51 Edited at: 30th Jun 2011 22:02
As Matty said, it's usually related to a memory corruption. The reason why it doesn't happen in debug mode is because the debug library allocates a bit of extra memory for you at every request. When you request, say - 10-bytes of memory, you will actually receive 10-bytes plus some extra buffer space at the end. The extra buffer space is a "just in case" thing so that if you over-run your buffer, it won't necessarily blow up on you when you're running the debug build. However, it should inform you that you over-ran the buffer - via a call to OutputDebugString() I believe.

I see that you use alot of arrays in your code. So I would start there. Look for something like:



A more subtle bug, and probably more applicable to your case now that I took another look at your code, is such:

I see that you call delete [] quite a bit. The problem is that you are not checking to see if there really is something to delete [] first. You should do a check for NULL first as in:



Fortunately, GDK has the above snippet already wrapped up into a nice little macro:



Now why would this be more subtle you ask? Because in Debug mode, any value that you don't intialize will default to something. Pointers will default to NULL. In Release mode, no such default initialization takes place. Because if this, it's best if you initialize everything yourself all of the time. That way you have a known state to work from. The following code is not the same between debug and release:



In debug build, pInt=NULL but in release build, pInt=??? (whatever value is already in that location). In this case, the SAFE_DELETE() macro would see a value other than NULL in pInt and continue with the delete operation - Gotcha!

Instead, use this code:



This time we've initialized the value ourself to a known state (NULL) and SAFE_DELETE() would not attempt to perform the delete operation unless we've actually made a change.

I hope this gives you some guidance on what to look for. Be warned though, it may be tough to spot!

Regards,

JTK

Edit: Added SAFE_DELETE() / SAFE_DELETE_ARRAY() distinction.
Hawkblood
14
Years of Service
User Offline
Joined: 5th Dec 2009
Location:
Posted: 1st Jul 2011 01:26
Is there ANY functional difference between SAFE_DELETE and SAFE_DELETE_ARRAY ?

The fastest code is the code never written.
Matty H
16
Years of Service
User Offline
Joined: 7th Oct 2008
Location: England
Posted: 1st Jul 2011 01:41
Quote: "Is there ANY functional difference between SAFE_DELETE and SAFE_DELETE_ARRAY ?"


Yes, it's quite important you use the correct one. I presume SAFE_DELETE will only free the memory at index 0 of your array, this would create a memory leak.

Hawkblood
14
Years of Service
User Offline
Joined: 5th Dec 2009
Location:
Posted: 1st Jul 2011 02:11
You "presume"? I have read some on this topic and I can see no difference.... I am sure there is some difference, but I can't seem to figure out when I should use one over the other. I mean, technically an array is a chunk of memory that is allocated-- the same thing for any allocation of memory..... The objects I am "deleting/safe delete/safe delete array" are class pointers that I may or may not be using with each menu item. I have changed the code to read this:

I still get the same results. I even tried taking out the "_ARRAY" part of the safe delete and same same. I'm really not even sure if this is what is causing the crash; it could be :

I took this part out and it seemed to work. I tried to narrow it down by taking out only portions of it and couldn't find it. So I put it all back one at a time and each item I put in caused the same result. So I started over and took everything out and it crashed. I'm sure I have some kind of memory leak, but I can't find it-- it seems to move.

The fastest code is the code never written.
JTK
14
Years of Service
User Offline
Joined: 10th Feb 2010
Location:
Posted: 1st Jul 2011 05:34 Edited at: 1st Jul 2011 05:45
Quote: "Is there ANY functional difference between SAFE_DELETE and SAFE_DELETE_ARRAY?"


A rule of thumb to follow is:

Quote: "
when you use new -> you must call delete -> SAFE_DELETE()
when you use new[] -> you must call delete[] -> SAFE_DELETE_ARRAY()
"


I'm sure the differences are via the C++ specification for the cases where class::operator new() and class::operator new[]() are overloaded.

Recall that you can overload each of the operator new() / operator new[]() / and related operator delete() / operator delete[]() functions at the global (: scope and class (class: method scope at any time you want to.

Therefore, since you can not be sure of what operator new()/new[]() will be called (especially with 3rd party libraries) you should always use the quoted rules above.

So, in short, even though it may appear that there's not any difference between the two for your case at the moment, rest assured that using your current approach will no-doubt be the cause of some future issue that you encounter. Live by the rules above and you shouldn't ever have to worry about it again...

Regards,

JTK

Edit: Something about your changes has struck a chord with me. My programmer senses are tingling. Could you show the code that actually 1) Initializes each of the variables (MenuItem[i].Caption et. al) and 2) Creates the addresses in question?
Hawkblood
14
Years of Service
User Offline
Joined: 5th Dec 2009
Location:
Posted: 1st Jul 2011 17:13 Edited at: 1st Jul 2011 19:08
I think I have found my problem. It's the menu I am loading. There must be something wrong with it so that when it unloads I'm trying to release something that is not there.


EDIT:
Yup! That was it. I had a corrupt MenuItem. I deleted it, reinitialized it and that fixed the problem.

The fastest code is the code never written.
Mireben
16
Years of Service
User Offline
Joined: 5th Aug 2008
Location:
Posted: 3rd Jul 2011 17:27
Just a remark:
Quote: "The problem is that you are not checking to see if there really is something to delete [] first. You should do a check for NULL first"


Not necessary. Deleting a null pointer is always safe (it doesn't do anything). It's also unnecessary to use the NULL macro because in C++ its value is just 0.

But it's true that variables must always be initialized before they are used.
Dashiznitz
13
Years of Service
User Offline
Joined: 25th May 2011
Location:
Posted: 10th Jul 2011 09:15
also why even say dbSpriteExist(xxx) == 1? if it is there it will already be true just put if (dbSpriteExist(XXX) ).

-Trying to get better
TerryRussell
13
Years of Service
User Offline
Joined: 11th Dec 2010
Location: Chichester, UK
Posted: 10th Jul 2011 12:06
Quote: "also why even say dbSpriteExist(xxx) == 1? if it is there it will already be true just put if (dbSpriteExist(XXX) )."


It shouldn't make any difference. The compiled code should take just as many machine cycles to do the test.

Amazing Simulation
www.amazing-forum.com
zog
16
Years of Service
User Offline
Joined: 13th Dec 2007
Location: Southport UK
Posted: 17th Jul 2011 12:22
Be careful you are not exceeding the handle bounds of the objects you are trying to destroy I recommend staying below 65535. Some dbobjects such as bitmaps only have 32 assignable values.

Jack Taylor
Hawkblood
14
Years of Service
User Offline
Joined: 5th Dec 2009
Location:
Posted: 18th Jul 2011 20:06
Good to know. Thanks.

The fastest code is the code never written.

Login to post a reply

Server time is: 2024-11-19 09:35:22
Your offset time is: 2024-11-19 09:35:22