Sign in to follow this  
Stormtrooper

boost::shared_ptr assert failed.

Recommended Posts

I have a font and image class based off of a resource class. I have a method in my resource manager class that cleans up unused resources... the lists are std::map<std::string, Image> and gcn::ImageFont>
// Font List
if( m_fontList[iter->name]->getReferences() == 0 )
{
	m_fontList[iter->name].reset();
	m_fontList.erase( m_fontList.find( iter->name ) );
}

// Image List
if( m_imageList[iter->name]->getReferences() == 0 )
{
	m_imageList[iter->name].reset();
	m_imageList.erase( m_imageList.find( iter->name ) );
}
My program fails an assert by boost::shared_ptr because of me calling getReferences. The variable the get returns is non-existent, and I have no idea why it isn't set. Here is how I add stuff to the list.
Image* ResourceManager::getImage( const std::string& name )
{
	// If the image is already loaded
	if( m_imageList[name] )
	{
		m_imageList[name]->incrementReferences();
		return m_imageList[name].get();
	}

	std::list<Asset>::const_iterator iter;

	for( iter = m_assetList.begin(); iter != m_assetList.end(); ++iter )
	{
		if( iter->name == name )
		{
			Asset asset = *iter;
				
			gcn::Image* tmp = m_imageLoader->load( asset.path );
				gcn::OpenGLImage* img = (gcn::OpenGLImage*)tmp;

			ImagePtr image( new Image( img->getTextureHandle(), img->getWidth(), img->getHeight() ) );
				
			delete tmp;

			image->incrementReferences();
			m_imageList[asset.name] = image;
				
			return image.get();
		}
	}
	logger.write( "ERROR: Image not in list" );
	return NULL;
}

gcn::ImageFont* ResourceManager::getFont( const std::string& name )
{

	// If the font is already loaded
	// return it
	if( m_fontList[name] )
	{
		m_fontList[name]->incrementReferences();
		return m_fontList[name].get();
	}

	// else...load it
	std::list<Asset>::const_iterator iter;

	for( iter = m_assetList.begin(); iter != m_assetList.end(); ++iter )
	{
		if( iter->name == name )
		{
			Asset asset = *iter;

			ImageFontPtr font( new ImageFont( asset.path, asset.arg ) );

			m_fontList[asset.name] = font;
			m_fontList[asset.name]->incrementReferences();

			return font.get();
		}
	}
	logger.write( "ERROR: Font not in list" );
	return NULL;
}

Share this post


Link to post
Share on other sites
Just a couple of quick questions to get things started...

1. What is the reference counting for? (Keep in mind that shared_ptr handles its own reference counting.)

2. Why are you returning a raw Image pointer rather than a shared pointer? That kind of defeats the purpose of using shared pointers...

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Just a couple of quick questions to get things started...

1. What is the reference counting for? (Keep in mind that shared_ptr handles its own reference counting.)

2. Why are you returning a raw Image pointer rather than a shared pointer? That kind of defeats the purpose of using shared pointers...


1. I wasn't sure if it had that functionality built in or not, or if it did house cleaning on its own.

2. Being desperate to get code to work.


So should I not implement reference counting since I'm using smart pointers...cause that would solve all my problems.

Share this post


Link to post
Share on other sites
Quote:
Original post by Stormtrooper
So should I not implement reference counting since I'm using smart pointers...cause that would solve all my problems.
Right.

The shared_ptr class keeps a reference count for the object assigned to it. When the last shared pointer referencing the object goes out of scope or is otherwise re-assigned (e.g. via reset() or swap()), the object is automatically destroyed and the memory freed.

As such, it is important that you only access the held object via a smart pointer; acquiring and passing around a raw pointer to the object defeats the purpose.

There are some other issues (or at least potential issues) in your code - maybe I can get to those in another post.

Post back if you need any further clarification.

Share this post


Link to post
Share on other sites
Quote:
Original post by Stormtrooper
Okay I think I found the possible problem...its not letting me compile because if I can't find it in the list, I can't return anything. So I need to figure out the best way to handle the error.

Any ideas?
One way or another you'll have to decide what to do when a requested resource is missing. Options include:

1. Assert.

2. Throw an exception.

3. Return an empty shared pointer.

4. Return an empty ('zombie') resource.

Option 1 is kind of brittle, IMO. The other three are all valid options, each with their own advantages and disadvantages:

- Throw an exception

Ok if the resource absolutely must be there, and, under normal circumstances, will be there. Not so good for resources that are in flux, or that might be open to player modification.

- Return an empty shared pointer

Leaves the caller with the responsibility of checking every resource pointer it requests for validity, which is easy to forget to do. And anyway, what do you do if an empty pointer is returned? You can assert, but shared_ptr will generally do that anyway if you try to dereference it while it's empty.

- Return a 'zombie' resource

If you return an 'empty' (i.e. functional but inoperative) resource, the rest of your program can go about its business, regardless of whether the resource could be found. The downside is that each resource for which this is a possibility then needs to know how to act in its 'zombie' state. For example, an OpenGL texture object might bind a plain white texture, while a sound object would simply not play.

There are probably other approaches as well, so I'm sure you'll get other suggestions. (Resource management is kind of a big topic, so the above is by necessity rather cursory...)

For what it's worth, in my current project I either throw an exception or return a 'zombie' resource, depending on the context.

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