Need some help on dynamic memory allocation (actually, de-allocation) as I'm re-navigating the learning waters for C++.

Say I have 2 classes -

class BulletCollection; class Bullet;

BulletCollection is responsible for instantiating / destroying Bullet objects by allocating new Bullet instances and storing the pointer in its std::map\ so it can be iterated through, etc. Looks something like:

Bullet is, well, a bullet. Has a TTL (time to live), which decreases when Bullet::update() is called. When TTL \< 0, it will call BulletCollection::killBullet( id ); See, in my class Bullet I store a BulletCollection* BC that points to the BulletCollection it belongs to. So my Bullet::update() looks like this:

... as I just typed that, I realize a potential problem... should I be doing:

delete *blist[in_id]; instead of delete blist[in_id]; ???

My entire code works and keeps running if my Bullet TTL is infinitely large, so I know it's a problem with entity destruction. Can someone please give me some insight?

Kenneth_Gorking
—
2011-03-16T16:09:15Z —
#2

I can't see how ' blist[in_id].erase();' could possibly compile. It should be ' blist.erase(in_id);'

oisyn
—
2011-03-16T16:09:27Z —
#3

No. The operand to 'delete' must be a pointer to the object you are trying to destroy, so dereferencing it first makes no sense.

However, take a good look at what you're doing. You first destroy the object, and after it's destruction, you tell it to remove itself from the map. How can you tell an object something if it's already destroyed?

So you have to reverse the order of things. Or you could simply use the erase() method on the map using the index of the bullet.

I believe something wonky is happening when I do blist.erase( bulletid )... When the crash happens, some file called xtree is opened up in my Visual Studio. Please help, I'm pulling hairs out over here.

BTW, even when I comment out // delete btemp; it still crashes, so it's probably blist.erase

Thanks,

Flamesilver

oisyn
—
2011-03-17T20:35:08Z —
#6

Ah, classic mistake You're iterating over the map, but while you're iterating, you're deleting items. The 'iter' variable in BulletCollection::update() is still referencing an element that is already removed from the map, and incrementing that invalid iterator and dereferencing it will result in undefined behavior.

To circumvent the problem, you could increment the iterator before you call Bullet::update(), so you know which iterator to use in the next iteration of the loop.

Be aware of the iterator invalidation rules of various containers. For a std::map it is defined that only iterators to deleted items become invalidated. But for a std::vector, however, any iterator that points to or past the deleted element is invalidated.

Flamesilver
—
2011-03-18T10:59:20Z —
#7

Thanks for the help oisyn. The iterator range problem is fixed and I'm no longer crashing with Fatal Error. But now I'm getting a heap corruption error.

Previously --ttl; was after the killbullet call, so it would try and write to a variable that was deleted.

Thanks for telling me about the rules of Heap. Devmaster.net is so awesome!

PS: Without you guys, I wouldn't've gotten very far. So far I've got a 3D space game with overhead fixed camera, overhead chase, and 3rd person camera view, full physics implemented via fulcrum, and I can fire bullets that interact with other ships (and give knockback). Soon I'll have a working game! Thanks guys!