Game Development Community

Random bug in GFXD3D9VertexBuffer::lock

by Lukas Joergensen · in Torque 3D Professional · 06/01/2012 (12:08 pm) · 5 replies

I am getting a bug which i suspect has it's origin in my custom emitter, the GraphEmitter class.
The thing is, this is a bug that just comes all of a sudden. I have no way to recreate it besides creating a lot of emitters and stare at them for 5 minutes.
The Call Stack in Visual Studio gives me this:
ntdll.dll!776515de() 	
 	[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]	
 	ntdll.dll!776515de() 	
 	ntdll.dll!7764014e() 	
 	KernelBase.dll!756cb9bc() 	
 	EmptyProject_DEBUG.dll!operator new[](unsigned int count)  Line 6 + 0x9 bytes	C++
 	EmptyProject_DEBUG.dll!GFXD3D9VertexBuffer::lock(unsigned int vertexStart, unsigned int vertexEnd, void * * vertexPtr)  Line 124 + 0xc bytes	C++
 	EmptyProject_DEBUG.dll!GFXVertexBufferHandleBase::lock(unsigned int vertexStart, unsigned int vertexEnd)  Line 94	C++
 	EmptyProject_DEBUG.dll!GFXVertexBufferDataHandle::lock(unsigned int vertexStart, unsigned int vertexEnd)  Line 215	C++
 	EmptyProject_DEBUG.dll!TSMesh::_createVBIB(GFXVertexBufferDataHandle & vb, GFXPrimitiveBufferHandle & pb)  Line 2311 + 0xc bytes	C++
 	EmptyProject_DEBUG.dll!TSSkinMesh::render(TSMaterialList * materials, const TSRenderState & rdata, bool isSkinDirty, const Vector<MatrixF> & transforms, GFXVertexBufferDataHandle & vertexBuffer, GFXPrimitiveBufferHandle & primitiveBuffer)  Line 1426	C++
 	EmptyProject_DEBUG.dll!TSShapeInstance::MeshObjectInstance::render(int objectDetail, TSMaterialList * materials, const TSRenderState & rdata, float alpha)  Line 739	C++
 	EmptyProject_DEBUG.dll!TSShapeInstance::render(const TSRenderState & rdata, int dl, float intraDL)  Line 520	C++
 	EmptyProject_DEBUG.dll!TSShapeInstance::render(const TSRenderState & rdata)  Line 436 + 0x27 bytes	C++
 	EmptyProject_DEBUG.dll!ShapeBase::prepBatchRender(SceneRenderState * state, int mountedImageIndex)  Line 2720	C++
 	EmptyProject_DEBUG.dll!ShapeBase::_prepRenderImage(SceneRenderState * state, bool renderSelf, bool renderMountedImages)  Line 2662	C++
 	EmptyProject_DEBUG.dll!Player::prepRenderImage(SceneRenderState * state)  Line 6947	C++
 	EmptyProject_DEBUG.dll!SceneRenderState::renderObjects(SceneObject * * objects, unsigned int numObjects)  Line 87	C++
 	EmptyProject_DEBUG.dll!SceneManager::_renderScene(SceneRenderState * state, unsigned int objectMask, SceneZoneSpace * baseObject, unsigned int baseZone)  Line 381	C++
 	EmptyProject_DEBUG.dll!SceneManager::renderSceneNoLights(SceneRenderState * renderState, unsigned int objectMask, SceneZoneSpace * baseObject, unsigned int baseZone)  Line 254	C++
 	EmptyProject_DEBUG.dll!PlaneReflector::updateReflection(const ReflectParams & params)  Line 625	C++
 	EmptyProject_DEBUG.dll!ReflectionManager::update(float timeSlice, const Point2I & resolution, const CameraQuery & query)  Line 167	C++
 	EmptyProject_DEBUG.dll!GuiTSCtrl::onRender(Point2I offset, const RectI & updateRect)  Line 298	C++
 	EmptyProject_DEBUG.dll!EditTSCtrl::onRender(Point2I offset, const RectI & updateRect)  Line 198	C++
 	EmptyProject_DEBUG.dll!GuiControl::renderChildControls(Point2I offset, const RectI & updateRect)  Line 558	C++
 	EmptyProject_DEBUG.dll!GuiControl::onRender(Point2I offset, const RectI & updateRect)  Line 428	C++
 	EmptyProject_DEBUG.dll!GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap)  Line 1728	C++
 	EmptyProject_DEBUG.dll!GuiCanvas::handlePaintEvent(unsigned int did)  Line 310	C++
 	EmptyProject_DEBUG.dll!fastdelegate::FastDelegate1<unsigned int,void>::operator()(unsigned int p1)  Line 990 + 0x1a bytes	C++
 	EmptyProject_DEBUG.dll!Signal<void __cdecl(unsigned int)>::trigger(unsigned int a)  Line 481	C++
 	EmptyProject_DEBUG.dll!Journal::Call<Signal<void __cdecl(unsigned int)>,unsigned int>(Signal<void __cdecl(unsigned int)> * obj, void (unsigned int)* method, unsigned int a)  Line 542 + 0xa8 bytes	C++
 	EmptyProject_DEBUG.dll!JournaledSignal<void __cdecl(unsigned int)>::trigger(unsigned int a)  Line 64 + 0x12 bytes	C++
 	EmptyProject_DEBUG.dll!GuiCanvas::paint()  Line 1490	C++
 	EmptyProject_DEBUG.dll!fastdelegate::FastDelegate0<void>::operator()()  Line 905 + 0x16 bytes	C++
 	EmptyProject_DEBUG.dll!Signal<void __cdecl(void)>::trigger()  Line 463	C++
 	EmptyProject_DEBUG.dll!Process::processEvents()  Line 78	C++
 	EmptyProject_DEBUG.dll!StandardMainLoop::doMainLoop()  Line 586 + 0x5 bytes	C++
 	EmptyProject_DEBUG.dll!torque_enginetick()  Line 103 + 0x5 bytes	C++
 	EmptyProject_DEBUG.dll!TorqueMain(int argc, const char * * argv)  Line 370 + 0x5 bytes	C++
 	EmptyProject_DEBUG.dll!torque_winmain(HINSTANCE__ * hInstance, HINSTANCE__ * __formal, char * lpszCmdLine, HINSTANCE__ * __formal)  Line 445 + 0x17 bytes	C++
>	EmptyProject_DEBUG.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpszCmdLine, int nCommandShow)  Line 47 + 0x16 bytes	C++
 	EmptyProject_DEBUG.exe!__tmainCRTStartup()  Line 275 + 0x2c bytes	C
 	EmptyProject_DEBUG.exe!WinMainCRTStartup()  Line 189	C
 	kernel32.dll!768e339a() 	
 	ntdll.dll!77669ef2() 	
 	ntdll.dll!77669ec5()

This is the assembler code where it happens:
--- f:ddvctoolscrt_bldself_x86crtsrcnewaop.cpp --------------------------
// newaop -- operator new[](size_t) REPLACEABLE
#include <new>

void *__CRTDECL operator new[](size_t count) _THROW1(std::bad_alloc)
	{	// try to allocate count bytes for an array
11639400  mov         edi,edi  
11639402  push        ebp  
11639403  mov         ebp,esp  
	return (operator new(count));
11639405  mov         eax,dword ptr [count]  
11639408  push        eax  
11639409  call        operator new (108774AFh)  
1163940E  add         esp,4  
	}
11639411  pop         ebp  
11639412  ret

And the exception says:
Unhandled exception at 0x776515de in EmptyProject_DEBUG.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0018a0b8..

#1
06/01/2012 (12:22 pm)
Oh it's a memory leak. Any good tips on how to trace one of those down? :)
#2
06/01/2012 (12:36 pm)
GlowCode is an outstanding tool, and they have a 30 day free trial I believe.
#3
06/01/2012 (12:52 pm)
Clearly my it shows that I am nothing but an initiate at programming :P
Put 2 delete functions in ( Actually no shit had never heard about that call before ) Never thought about memory leaks being an issue since i have only worked in small c# applications where it didn't matter really.
Oh well will have to update the Improved Particle System resource or else someone is gonna get mad when their games begin to crash :P

For anyone looking for a solution to this in the future:
In the addParticle code of the emitter class i have 2 points instantiated like this:
Point3F *point = new Point3F();
And when you create something using new, or create a pointer in general you will need to use the delete to clear the memory:
delete(point);
Sometimes you have to use free instead read about it here:
http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html
#4
06/01/2012 (1:09 pm)
Rule of thumb is to always delete what you create with new and free() what you allocate with malloc()/calloc(). Never ever mix those two procedures.
#5
06/01/2012 (1:12 pm)
From recent experiences, the engine will make sure to tell you that you have freed something you should have deleted by crashing instantly :P