Sign in to follow this  
jchmack

strange crash when recycling objects

Recommended Posts

ok rather than dynamically allocating each projectile each time an object is created im trying to "recycle" my objects. When a projectile is destroyed i just dont display it and don't do any calculations on it. But it still is within memory. I Want to make it where whenever i create a new object if there is an object in the InactiveProjectiles queue use that object otherwise dynamically make a new object.
if(InactiveProjectiles.empty()) //InactiveProjectiles is a list of projectile ptrs
	{
		temp = new Projectile;
		
		if(index!=-1)
		{
			*temp = ProjectileTypes[index];
		}

		temp->Create(mScene,GunNode,Target,Target2);

		Projectiles.push_back(temp);
	}


it works fine untill i try to "recycle" my projectiles: Unhandled exception at 0xe8570974 in game4.exe: 0xC0000005: Access violation reading location 0xe8570974. mActor CXX0030: Error: expression cannot be evaluated mEntity CXX0017: Error: symbol "" not found mNode CXX0017: Error: symbol "" not found
else
	{
		temp = InactiveProjectiles.front();
		InactiveProjectiles.pop();

		if(index!=-1)
		{
			//*temp = ProjectileTypes[index];// it crashes here if i uncomment this  ProjectileTypes is a vector of Projectiles.
		}

		//temp->Reactivate(mScene,GunNode,Target,Target2);
	}


it should all work fine and i dont know what is causing it to crash. the only differecne is: temp = new Projectile; vs temp = InactiveProjectiles.front();

Share this post


Link to post
Share on other sites
Quote:
Original post by jchmack
ok rather than dynamically allocating each projectile each time an object is created im trying to "recycle" my objects. When a projectile is destroyed i just dont display it and don't do any calculations on it. But it still is within memory. I Want to make it where whenever i create a new object if there is an object in the InactiveProjectiles queue use that object otherwise dynamically make a new object.


Excellent idea, bad implementation. The usual approach to this is to use a pool allocator. Then, the memory is owned by the pool and automatically recycled, but you don't have to manually keep track of unused memory: you new Object() and then delete pObj after having overloaded new and delete for your class to use a pool allocator.

A simple example below:


// Usage:
Object* o1 = new Object(); // Allocates memory
delete o1; // Places memory in memory pool

Object* o2 = new Object(); // Uses pool memory without allocation

// Implementation:
class Object
{
public:

// How to allocate memory for this object
void* operator new(std::size_t alloc)
{
assert (alloc == sizeof(Object));

if (pool.empty) return ::operator new(alloc);

void* data = pool.top();
pool.pop();
return data;
}

// How to deallocate memory for this object
void operator delete(void* recycled, std::size_t size)
{
assert (size == sizeof(Object));
if (recycled) pool.push(recycled);
}

private:

// A pool of free memory
static std::stack<void*> pool;
};




As for your code, what is the type of InactiveProjectiles? What specific line does the debugger complain about, is the value of the pointer on that line the same as when you added the pointer to the pool, and have you deallocated the pointer in one way or another since then?

Share this post


Link to post
Share on other sites
wow i had no idea you could overload new/delete like that. But im not to familiar with manually managing memory that way and would like to stick to letting the compiler do it for me (for now at least).

Quote:
Original post by ToohrVyk
As for your code, what is the type of InactiveProjectiles? What specific line does the debugger complain about, is the value of the pointer on that line the same as when you added the pointer to the pool, and have you deallocated the pointer in one way or another since then?


Sorry if i didn't make it clear enough i put comments labeling some of the objcects that you may not understand. InactiveProjectiles is a queue of pointers to projectiles that aren't active anymore. I deactivate them like this: ProjectileTypes is a vector of Projectile objects. These Projectiles are just templates that i just copy when creating a new projectile.


void ProjectileManager::Deactivate(Projectile *mProjectile)
{
mProjectile->Active = false;
mProjectile->mBody->putToSleep();
mProjectile->mBody->setGroup(mScene->findGroup("InactiveProjectiles"));
projectilebillboardset->removeBillboard(mProjectile->mBillboard);
InactiveProjectiles.push(mProjectile);
}




the debugger points at a line in a library im using (ogre3d).

im not exactly sure what you mean by "deallocated the pointer" If you mean use it like pointer->dosomething then yes i used it.

edit: i believe it has something to do with ProjectileTypes[index] not being initialized when i copy it. because one of the datatypes hasnt been assigned a value yet. But if this is the case why does it let me do it the first time? Im asking on the ogre forums if there is a way to assign this data type to a default value.

edit2: im going to try to copy each individual parameter

[Edited by - jchmack on March 10, 2007 10:30:42 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by jchmack
wow i had no idea you could overload new/delete like that. But im not to familiar with manually managing memory that way and would like to stick to letting the compiler do it for me (for now at least).


Fact: you are currently handling memory yourself — which is more or less the point when you're implementing a memory recycling scheme, so everything's right.

However, you are also handling object initialization yourself, instead of letting the compiler do so. For instance, you're reinventing constructors, and moving away from a clean "call new and be done" initialization protocol and "call delete and be done" cleanup protocol. So, why not let the compiler do the work for you?

Quote:
the debugger points at a line in a library im using (ogre3d).


Well, what does that line do ? What causes it, precisely, to go wrong? The general occurence in this kind of situation is that a piece of code receives the wrong kind of data (such as NULL, or garbage, or something else) and crashes. The process of debugging involves finding the problematic piece of code, and then backtracking through the program to determine where the wrong data came from.

Once you know where that data appeared, you can change the code at that point so it either creates correct data, or doesn't call the dangerous code when the data is invalide.

Quote:
im not exactly sure what you mean by "deallocated the pointer"


I meant, deallocated the memory pointed to by that pointer.

Quote:
But if this is the case why does it let me do it the first time?


Undefined behaviour? See my signature.

Quote:
Im asking on the ogre forums if there is a way to assign this data type to a default value.


Now, you're just looking for a hack to work around your design problem. Proper design would dictate that, if no default initialization is possible, you do not provide a default constructor, and provide a custom non-default constructor instead. However, your current reimplementation of constructors, being only a subset of the default C++ one, may prevent you from doing this.

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