Memory leak using STL List

Started by
16 comments, last by the_edd 16 years, 7 months ago
Hi, I am writing a simple 2d game demo and I store all of my projectiles in a list called ProjectileList and I check to see if they have gone off screen, in which I erase them from the list. I have noticed however that when I fire a projectile in game, the amount of memory the program takes up keeps growing and never goes down. So I believe it is most likely to do with how I am getting rid of my projectiles... Here is my code... that should help

std::list<Projectile*> ProjectileList;
...
...
void Player::fireProjectile()
{
	Projectile *projectile;
	projectile = new Projectile(5000);

	D3DXVECTOR3 playerPos = GetPosition();

	playerPos.x += 64;
	playerPos.y += 32;

	projectile->Init("projectile.tga", 16, D3DXVECTOR3(playerPos.x, playerPos.y, 0), true);

	ProjectileList.push_back(projectile);
}
...
...
// Remove projectiles
for( std::list<Projectile*>::iterator node = ProjectileList.begin(); node != ProjectileList.end(); )
{
	if((*node)->IsDead())
	{
		(*node) = NULL;
		node = ProjectileList.erase(node);
	}
	else
	        ++node;
	}
I do know the remove projectiles area is being called as my projectiles and other objects I use similar code will stop rendering and updating when the erase has been called.
Advertisement
You must delete everything you new. Removing an item from a std::list will not deallocate the object in memory.
I tried something like...

(*node) = NULL;
delete (*node);
node = ProjectileList.erase(node);

But didn't seem to make a difference.
Quote:Original post by matth
I tried something like...

(*node) = NULL;
delete (*node);
node = ProjectileList.erase(node);

But didn't seem to make a difference.


You're NULLing the pointer before you delete it, so the memory still isn't getting deallocated.

Try:
delete (*node);
node = ProjectileList.erase(node);

There's really no need to make the pointer NULL at all.
Thanks - I have done that so potentially my memory leak might be someplace else...
It's worth noting that task manager isn't a good indication of how much memory you're using. It's unlikely to go down much because the runtime library will keep blocks of memory around in case you want to allocate memory again.

Although, if it keeps going up, it's a rough indication that you're leaking memory somewhere.
Yea, basically I just have a simple game coded directly in Direct X 9 using LPDIRECT3DTEXTURE9's for my player and projectiles. Here is the Sprite class that handles them both.

... deleted my code since i narrowed down where leak was occuring


[Edited by - matth on September 15, 2007 3:58:02 PM]
If you're worried about memory leaks/memory consumption, get a copy of valgrind and test your programme with that...

--random
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
I've narrowed down where the leak was occurring, which again goes to a list function.

I create the projSwap and enemySwap because I had trouble feeding the iterator into the SpriteCollisionTest functions. However, if I am to delete projSwap and enemySwap after, I am getting a crash - potentially because it is deleting the object at the address which is the same object that the iterator is storing the address of?

// Check for Collisionsfor( std::list<Projectile*>::iterator projNode = ProjectileList.begin(); projNode != ProjectileList.end(); ++projNode ){	Projectile *projSwap;	projSwap = new Projectile();	projSwap = (*projNode);	if(SpriteCollisionTest(dynamic_cast<Sprite&>(*projSwap), dynamic_cast<Sprite&>(*playerMothra)))	{		(*projNode)->Kill();	}	else	{				for( std::list<Enemy*>::iterator enemyNode = EnemyList.begin(); enemyNode != EnemyList.end(); ++enemyNode )		{			Enemy *enemySwap;			enemySwap = new Enemy();			enemySwap = (*enemyNode);						if(SpriteCollisionTest(dynamic_cast<Sprite&>(*projSwap), dynamic_cast<Sprite&>(*enemySwap)))			{				(*projNode)->Kill();				(*enemyNode)->Hit();			}                        delete enemySwap;		}	}	delete projSwap;}
Here:
Quote:
projSwap = new Projectile();
projSwap = (*projNode);


And here:
Quote:
enemySwap = new Enemy();
enemySwap = (*enemyNode);


You overwrite the pointers so you cannot call delete them.

I think you should investigate smart pointers. boost::shared_ptr<> is an excellent example.

Also, this:
Quote:if(SpriteCollisionTest(dynamic_cast<Sprite&>(*projSwap), dynamic_cast<Sprite&>(*playerMothra)))

Will not work as you intend, as a bad dynamic_cast on a reference will throw an exception (it cannot return a "null" reference because no such thing exists). It is one of the few times it is preferable to use a pointer over a reference.

This topic is closed to new replies.

Advertisement