Sign in to follow this  
d h k

Problem with boost::shared_ptr

Recommended Posts

For a game, I want to have a bunch of enemies which can be divided by type (ie. there are thousands of them but only - say - ten classes, for example gunner, grenadier, tank etc.) - so my approach to implement this in a memory-efficient way is the following: The Approach/Set-Up I have a global model structure for each class, like this:
// global scope
Model gunner_model, grenadier_model, tank_model;
Then there's a function that is called when the game starts that loads these models:
// on game start
void LoadEnemyModels ( void )
{
	gunner_model.Load ( "gunner_model.3ds", "gunner_texture.png" );
	grenadier_model.Load ( "grenadier_model.3ds", "grenadier_texture.png" );
	tank_model.Load ( "tank_model.3ds", "tank_texture.png" );
}
Next I have a class called 'Enemy' which includes all kinds of stuff such as a position, rotation, ammunition, whatever, and a pointer to a model:
class Enemy
{
	public:
		boost::shared_ptr<Model>	model;
		//Vector3			Position;
		// etc.
};
Now I define a global std::list of my Enemy class:
// global scope again
std::list<Enemy> enemy;
The Problem I use the following function for adding a new enemy to the vector:
void AddEnemy ( EnemyType type )
{
	Enemy _enemy;

	if ( type == Gunner )
		_enemy.model.reset ( &gunner_model );
	else if ( type == Grenadier )
		_enemy.model.reset ( &grenadier_model );
	else if ( type == Tank )
		_enemy.model.reset ( &tank_model );

	enemy.push_back ( _enemy );

	Console::Print ( "Enemy added   - new enemy count: %d", enemy.size ( ) );
}
And this one to get rid of one (which one is not important right now so I just go for the first entry in the list):
void RemoveEnemy ( )
{
	if ( enemy.size ( ) > 0 )
		enemy.erase ( enemy.begin ( ) );

	Console::Print ( "Enemy removed - new enemy count: %d", enemy.size ( ) );
}
So, when I push-back a new Enemy into the list, I make sure to set its pointer to the correct model according to the type that the new enemy should be of. Like this, however, whenever I call RemoveEnemy ( ) the game crashes with this:
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!

Program: c:\Game\Game.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
When I don't set the enemy's model-pointer to anything (leave it as NULL), and then don't try to draw it (access it), removing works fine. I'm assuming I'm doing something wrong with the boost::shared_ptrs, possibly when setting the smart pointer to point at the correct model structure? Also, is this approach valid? Does it make sense to do it all this way? Any help is appreciated!

Share this post


Link to post
Share on other sites
You're misusing shared_ptr here, making it point to a non-heap-allocated object and creating multiple shared_ptrs to the same object. On a more basic note, though, why are you using a smart pointer rather than a raw pointer in this instance? What do you intend for the smart pointer to handle for you?

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
You're misusing shared_ptr here, making it point to a non-heap-allocated object and creating multiple shared_ptrs to the same object.


Ah, didn't know you couldn't do that. I'm new to the boost::pointers.

Quote:
Original post by Sneftel
On a more basic note, though, why are you using a smart pointer rather than a raw pointer in this instance? What do you intend for the smart pointer to handle for you?


I was told to always use them, in this instance, though, using a normal raw pointer works flawlessly.

Thanks for the clear up, works fine now!

Share this post


Link to post
Share on other sites
Quote:
Original post by d h k
I was told to always use them, in this instance, though, using a normal raw pointer works flawlessly.
That doesn't answer my question. What does a shared_ptr do that a raw pointer doesn't? Hint: It's just one thing. (Answering this question will aid your understanding of smart pointers.)

Share this post


Link to post
Share on other sites
Quote:
Free its own memory automatically when it's not needed anymore?
Yup, pretty much.

Unless you're doing some unusual (such as constructing your shared pointers with a custom 'delete' function), shared_ptr will invoke delete on the held pointer when the reference count drops to zero.

So the next question is, what would you expect to happen when delete is invoked on a non-heap-allocated object, such as your global 'model' objects?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this