Weirdo C++ problem (dynamic memory, it seems)

GEC: Discuss gaming, computers and electronics and venture into the bizarre world of STGODs.

Moderator: Thanas

Post Reply
User avatar
Dooey Jo
Sith Devotee
Posts: 3127
Joined: 2002-08-09 01:09pm
Location: The land beyond the forest; Sweden.
Contact:

Weirdo C++ problem (dynamic memory, it seems)

Post by Dooey Jo »

So I have this code, which creates a few inherited classes (which I will henceforth call "sprites") and adds their pointers to my sprite rendering vector, and a vector to keep track of which sprites were created (these sprites are sort of parented to another class, obviously I don't keep all sprites in two vectors...) at one point, and at a later time, some more sprites may be created, or some of them may be removed. Now, all of this would work fine, if it wasn't for one small issue, which is the weirdo bug:

Sometimes a newly created sprite has the same address as an old sprite, which has not yet been deleted (and one time, I think a new one had the same address as a previously deleted sprite, but it crashed anyway). Obviously this is very bad, and even more annoying is that this does not seem to happen in debug mode. I was only able to pinpoint the strange crashes that happened by using low-tech error logging files (and it doesn't crash when the sprites are created, or even rendered, only later when I try to use a sub-class method, so maybe it's only able to partially create the offending classes, though the log files suggests otherwise)... I do exception handling, tests for NULL pointers, but to no avail. "new" seems to work as it should, only something goes horribly wrong.

Does anyone have any idea as to what might cause this? It's not even a compiler issue either, it happens on both GCC and Visual Studio, so my code must be broken somehow. I just don't know where to look (and I've checked the constructors and destructors, and just about everything I can think of (including rewriting so that it uses a linked list instead of a vector, and about a million other things), they really do seem to be working like they usually do).

Help, please. :(
Image
"Nippon ichi, bitches! Boing-boing."
Mai smote the demonic fires of heck...

Faker Ninjas invented ninjitsu
Crazy_Vasey
Jedi Council Member
Posts: 1571
Joined: 2002-07-13 12:56pm

Post by Crazy_Vasey »

Sounds like you've got a buffer overflow sonewhere to me. Bizarre, intermittant problems that don't occur in debug mode? Yeah, that sounds like a buffer overflow alright. Extra memory is generally allocated as guards around newed arrays and such in debug mode which makes finding off by one errors ever so much fun.
User avatar
Beowulf
The Patrician
Posts: 10621
Joined: 2002-07-04 01:18am
Location: 32ULV

Post by Beowulf »

You can still debug with it in release config in Visual Studio. It just doesn't work quite as well.
"preemptive killing of cops might not be such a bad idea from a personal saftey[sic] standpoint..." --Keevan Colton
"There's a word for bias you can't see: Yours." -- William Saletan
User avatar
Mad
Jedi Council Member
Posts: 1923
Joined: 2002-07-04 01:32am
Location: North Carolina, USA
Contact:

Post by Mad »

The only thing I can think of offhand is that maybe a sprite is getting its destructor called somewhere, but its pointer isn't being removed from the vector.

How short can you make the code so that it still exhibits the problem?
Later...
User avatar
Darth Paul
Sith Apprentice
Posts: 52
Joined: 2002-08-22 11:44pm
Location: Canada

Post by Darth Paul »

Debugging the Release build is a good suggestion to find the crash point - try turning off all optimizations and inlining in the release build, as this will help the debugger report your variable values better, or post some code if you can. In my experience, by far the most common source of debug/release differences is uninitialized (or un-reset) variables, since the debugger will initialize values to zero, which your code may be catching in debug when checking for NULL, etc, but it's really just guessing without seeing real code.
User avatar
Dooey Jo
Sith Devotee
Posts: 3127
Joined: 2002-08-09 01:09pm
Location: The land beyond the forest; Sweden.
Contact:

Post by Dooey Jo »

Thanks guys, I've solved it now. I always had a feeling it would turn out to be something retardedly simple, and that I would discover it three seconds after posting...

Both Mad and Crazy_Vasey were sort of correct. What was happening was that some sprites got destructed early because of an error in a slightly related piece of code, and the vector that kept track of them didn't know this (but the rendering vector did, which was why it didn't crash immediately), so yeah... I'm going to be ashamed of myself for a year now...

But thanks again everyone!
Beowulf wrote:You can still debug with it in release config in Visual Studio. It just doesn't work quite as well.
Destructionator XIII wrote:Ditto for g++ and gdb. Try g++ -ggdb -O2 for optimizations and debug info at the same time.
Yes, this was what I meant by the debug "mode" as opposed to a debug build.


Actually, I have another interesting error that only happens in Visual Studio. This one isn't critical, since I can fix it. I just want to know what's going on. Here's the code:

Code: Select all

void RunningStateMayor::ImgButtonClick(GUIImage* img) {
	if (mCurrArea == NULL) return; // An area must be set

	unsigned int p=0; // Get the index of the clicked image in the list
	for (GUIObjectList::iterator it=mImgButtons.begin();
		*it != img;
		it++,p++) {
		if (it==mImgButtons.end()) { // Apparently, this image is not in the list
			return; // And that should not happen (we could also throw here)
		}
	}
    
	// Get the list of types the current area can be transformed into
    const vector<int>& types = mCurrArea->GetInfo().transform;
    if (!types.empty() && p < types.size()) { // Make sure the index is valid
		// Visual Studio likes to crash if we use types[p] at other places
		// Why? I have no bloody idea...
//		int value = types[p];
		mCurrArea->Change(mMapAreaFactory.getAreaInfo(types[p])); // Change the area
        
		// Set up data to send over the network
		NetAreaChange data("");
		data.newType = types[p];
		int i=0;
		for (list<MapArea>::iterator it = mMapAreas.begin();
			&(*it) != mCurrArea; it++,i++) {
			if (it == mMapAreas.end()) {
				return; // Unusual behaviour (throw instead?)
			}
		}
		data.areaIndex = i;
		objects->net.sendData(&data);
	}
    
	[snip some more code]
}
I have to use the (here commented out) variable "value" instead of "types[p]" otherwise it crashes the second time it is used, ie in "data.newType = types[p]". Isn't that interesting...
Image
"Nippon ichi, bitches! Boing-boing."
Mai smote the demonic fires of heck...

Faker Ninjas invented ninjitsu
User avatar
Dooey Jo
Sith Devotee
Posts: 3127
Joined: 2002-08-09 01:09pm
Location: The land beyond the forest; Sweden.
Contact:

Post by Dooey Jo »

Destructionator XIII wrote:Well, maybe it is getting confused since you change that thing in mCurrArea, and you are working with a reference to something inside it? If that change touches something in there, it might b0rk the const reference.

I'm just taking a random stab; I really don't know.
Yeah, it's really strange. The "Change()" function is working with a reference to a "mapAreaInfo" struct, but not only should that not affect the index or the vector, it is also const, and if it did change anything, the compiler would say so...
Image
"Nippon ichi, bitches! Boing-boing."
Mai smote the demonic fires of heck...

Faker Ninjas invented ninjitsu
User avatar
Durandal
Bile-Driven Hate Machine
Posts: 17927
Joined: 2002-07-03 06:26pm
Location: Silicon Valley, CA
Contact:

Post by Durandal »

Does your indexing operator implementation change the object's state in any way? Have you tried changing it to return a compile-time value to see if it gives you the same problem?
Damien Sorresso

"Ever see what them computa bitchez do to numbas? It ain't natural. Numbas ain't supposed to be code, they supposed to quantify shit."
- The Onion
User avatar
Dooey Jo
Sith Devotee
Posts: 3127
Joined: 2002-08-09 01:09pm
Location: The land beyond the forest; Sweden.
Contact:

Post by Dooey Jo »

Durandal wrote:Does your indexing operator implementation change the object's state in any way? Have you tried changing it to return a compile-time value to see if it gives you the same problem?
Well it's an STL vector, and since it is const, it really shouldn't. Though I've heard that VS has a history of weird STL implementations (even though this is VS 8)...
Image
"Nippon ichi, bitches! Boing-boing."
Mai smote the demonic fires of heck...

Faker Ninjas invented ninjitsu
Post Reply