TSMesh::render() & TSMesh::smObject accessing deleted memory
by Robert Rose · in Torque Game Engine Advanced · 01/27/2008 (1:58 am) · 3 replies
I've got a random crash that I finally caught in a journal last night and have been tracking down the cause. The crash is a __non_rtti_object exception but it looks like that's just a symptom, after investigation I discovered that what was throwing the exception was an access to TSMesh::smObject in TSMesh::render().
TSMesh::smObject appears to be referencing deleted memory, it's set completely to 0xcececece. To try and catch the problem earlier I set a trap in operator delete to check to see if the deleted memory range contained TSMesh::smObject. Sure enough, right before the crash Torque deletes the memory referenced by TSMesh::smObject.
The deleted object is an AIPlayer that has just died and is in the process of getting cleaned up. The deletion comes from a network message; the actual delete is done in SimObject::deleteObject().
Moments later, in the same frame, SceneGraph::treeTraverseVisit() gets called from WaterBlock::updateReflection() and the second object to be rendered is a Projectile. Now here's where my understanding of TSMesh::smObject breaks down--Projectile::prepBatchRender() results in a call to TSMesh::render() which then refers to TSMesh::smObject, which is set to the AIPlayer that got deleted. I don't know how smObject is intended to be used, but shouldn't it be the projectile?
Any ideas? This bug is causing me to lose sleep. :)
TSMesh::smObject appears to be referencing deleted memory, it's set completely to 0xcececece. To try and catch the problem earlier I set a trap in operator delete to check to see if the deleted memory range contained TSMesh::smObject. Sure enough, right before the crash Torque deletes the memory referenced by TSMesh::smObject.
The deleted object is an AIPlayer that has just died and is in the process of getting cleaned up. The deletion comes from a network message; the actual delete is done in SimObject::deleteObject().
Moments later, in the same frame, SceneGraph::treeTraverseVisit() gets called from WaterBlock::updateReflection() and the second object to be rendered is a Projectile. Now here's where my understanding of TSMesh::smObject breaks down--Projectile::prepBatchRender() results in a call to TSMesh::render() which then refers to TSMesh::smObject, which is set to the AIPlayer that got deleted. I don't know how smObject is intended to be used, but shouldn't it be the projectile?
Any ideas? This bug is causing me to lose sleep. :)
#2
01/28/2008 (8:47 am)
Looks like you found a bug, and fixed it. Good fix!
#3
coreRI->calcSortPoint( smObject, smSceneState->getCameraPosition() );
There are several more instances of smObject around the code, set with that TSMesh::setObject line. Never seen that particular crash but I did find some other cases where the smObject wasn't valid and needed to be set. I think was in guiObjectView, but can't tell now.
02/06/2008 (5:06 am)
Yes, that makes sense. smObject needs to be set in order for this line to work correctly in TSMesh Render, used to calculate what looks like z sorting. TSMesh::render uses the smObject global, so it better be valid or NULL before the render happens!coreRI->calcSortPoint( smObject, smSceneState->getCameraPosition() );
There are several more instances of smObject around the code, set with that TSMesh::setObject line. Never seen that particular crash but I did find some other cases where the smObject wasn't valid and needed to be set. I think was in guiObjectView, but can't tell now.
Torque Owner Robert Rose
void Projectile::prepBatchRender(SceneState* state) { // DAW: New code for TSE MatrixF proj = GFX->getProjectionMatrix(); RectI viewport = GFX->getViewport(); state->setupObjectProjection(this); // hack until new scenegraph in place MatrixF world = GFX->getWorldMatrix(); TSMesh::setCamTrans( world ); TSMesh::setSceneState( state ); TSMesh::setObject(this); // <--- here's what I added ...Can someone with some expertise here please comment on this? :-) Is this a safe thing to be doing? I'm probably still going to lose sleep over this. :-)