Jump to content
  • Advertisement
Sign in to follow this  
sqpat

[SOLVED] release() not working? (memory leaks...)

This topic is 3757 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

im using PIX to try and track down memory leaks in my program. Im down to the point where the only real resources i have left are the d3d9 object and device, some resources created by direct3d and d3dx... and then one other resource. Basically, every frame i'm creating a vertex buffer in a method. and at the start of this method, i release the buffer first. all works well till the end; after the end of my main game loop, i do another release of the object. However, it doesnt seem to get released; and then i look at the object viewer in the PIX experiment, and there is the object, still alive upon the end of execution. http://i38.tinypic.com/33m4r3a.png my release() call is exactly the same both in the method and after the end of the main loop... the vertexbuffer pointer is a global variable... also, its the final vertexbuffer to be used, but i used SetStreamSource with the null argument afterwards so it should be releasing. Or is there another thing i have to do to free up the buffer? i can show code if it helps. I'm not sure what to do about it at this point, but im sure its something common and newby since this is my first time cleaning up direct3d memory leaks. [Edited by - sqpat on August 3, 2008 8:08:53 PM]

Share this post


Link to post
Share on other sites
Advertisement
Quote:
i look at the object viewer in the PIX experiment, and there is the object, still alive

What do you mean by "still alive?" More importantly, what indication do you have that you have a memory leak?


[Edited by - Buckeye on August 2, 2008 10:40:27 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Buckeye
What do you mean by "still alive?" More importantly, what indication do you have that you have a memory leak?


I ran it with the debug runtime using the directx console and set breakpoints for memory leaks. One comes up upon the end of execution. Additionally, looking at what PIX is telling me, at the end of execution there are a couple of "live" pointers, i.e. they havent been deleted or released. That's how PIX defines if a memory region has been released or not; it's 'live', or 'dead'.

Quote:
Original post by Buckeye
Just because a memory pointer points to a recognizable object doesn't mean that object is useable. The memory pointed to may not be modified recognizably when the object is released. It may be written over later but, if PIX thinks it's a pointer to a vertex buffer and doesn't "know" it's released, it will faithfully interpret what it sees.


Well, the other stuff suggests that there is a memory leak, and the only other "live" pointers are the device/object pointers, and a couple that were created not by the application . i assume these would be released when the device/object stuff got released, which would get released when the vertex buffer got released.

Quote:
Original post by BuckeyeBy the way, a good programming practice is to set a pointer to NULL when you're done with it. First: initialize all your pointers to NULL. Then use a macro like the following to release your objects:
#define RELEASE(x) { if(x!=NULL) x->Release(); x=NULL; }



woo, thats pretty cool. thanks.

Share this post


Link to post
Share on other sites
How about posting the code, then, for the routine where you release and create the buffer?

Do you initialize all your DirectX pointers to NULL in some constructor or at the initialization of your app?

Share this post


Link to post
Share on other sites
here's my main function. a lot of my directx pointers are global vars.


int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreviousInstance,LPSTR lpcmdline,int nCmdShow){

srand( (unsigned)time(0) ); // should be done early

MSG msg_Message;

HWND han_Window = NewWindow("sqpat is awesome",100,100,640,480);
LPDIRECT3D9 p_dx_Object = Direct3DCreate9(D3D_SDK_VERSION);

LPDIRECT3DDEVICE9 p_Device = InitializeDevice(han_Window, p_dx_Object);

init_Sound(han_Window);

init_Char(han_Window, p_Device);

LPDIRECT3DVERTEXBUFFER9 p_dx_VB = init_Map(mapID, han_Window, p_Device);
LPDIRECT3DINDEXBUFFER9 p_dx_IB = FillIndices(han_Window, p_Device);
InitializeFont(han_Window, p_Device);
InitializeKeyboard(han_Window);
InitializeJoystick(han_Window);
SetupBackground(han_Window, p_Device);

OggPlayer op; // ogg player object
char musicName [40];
getMusicFilename(musicID, musicName);

op.InitDirectSound(han_Window);
op.OpenOgg(musicName); // oggplay startup
long tempInta = musicLoop;
op.Play(true, musicLoop); // oggplay with looping and loop point.

g_timer.StartTimer();

// START MAIN GAME LOOP

while(int_AppRunning){
if(PeekMessage(&msg_Message,han_Window,0,0,PM_REMOVE)){
DispatchMessage(&msg_Message);
}
if (!joystickFound) // If joystick not found
ReadKeyboard(inputKeyboard); // Read input from keyboard
else // else, (if joystick found)
ReadJoystick(inputJoystick, han_Window); // Read input from joystick

SetupBackground(han_Window, p_Device); // redraws bg for rotations
moveChars(); // Move characters and do physics crap
SetUpCamera(p_Device); // Adjust Camera
getSpriteFacing(); // Get Sprites' Camera-relative facing
updateAnimations(); // Get Sprites' Current frame.
DrawScene(p_Device, p_dx_VB, p_dx_IB, han_Window); // Output graphics display
maintainSound(); // Maintains SFX handling
if (op.IsPlaying()) // need this check in case you dont have looping and it stops
op.Update(); // Update ogg player
animateCounter++;
if (animated)
if (animateCounter == (animateNum * animateLength))
animateCounter = 0;
}

// END MAIN GAME LOOP


RELEASE(inputObject);
if (inputKeyboard != NULL){
inputKeyboard->Unacquire();
RELEASE(inputKeyboard);
}
if (inputJoystick != NULL){
inputJoystick->Unacquire();
RELEASE(inputJoystick);
}

RELEASE(p_dx_VB);
RELEASE(p_dx_IB);
RELEASE(p_dx_font);
RELEASE(myCyl);


for (int a = 0; a < numText; a++)
RELEASE(Texture[a]);
for (int a = 0; a < numChars; a++){
RELEASE(charSpriteFrames[a]);
}


DestroyWindow(han_Window);
delete [] charSpriteFrames;
delete [] charPos;
delete [] Texture;
delete [] textureMap;

sPerformance->Stop(NULL,NULL,0,0); //stop all playing music
RELEASE(sLoader); //release loader object

sPerformance->CloseDown(); //close down performance object
RELEASE(sPerformance); //release performance object
op.Close();
CoUninitialize(); //uninitialize COM


RELEASE(p_Device);
RELEASE(p_dx_Object);

return 0;
}





and heres where i create and release the vertex buffer



void SetupBackground(HWND han_Window, LPDIRECT3DDEVICE9 p_dx_Device){

OURCUSTOMVERTEX *cyl_Verts = new OURCUSTOMVERTEX[cylPrec*2];

if (myCyl != NULL)
RELEASE(myCyl);

float offset = (theta/(D3DX_PI));

for( int i=0; i<cylPrec; i++ ){
FLOAT cylTheta = (2*D3DX_PI*i)/(cylPrec-1)/2.0f;
cyl_Verts[2*i+0].y = -(extendMapValue*.8f) * sinf(cylTheta-theta+(D3DX_PI/2))+WIDTH/4;
cyl_Verts[2*i+0].x = (extendMapValue*.8f) * cosf(cylTheta-theta+(D3DX_PI/2))+HEIGHT/4;
cyl_Verts[2*i+0].z = 0;
cyl_Verts[2*i+0].color = 0xffffffff;
cyl_Verts[2*i+0].u = mapStretch * (offset - ((float)i)/(cylPrec-1));
cyl_Verts[2*i+0].v = 1.0f;
cyl_Verts[2*i+0].normal.x = (float)1;
cyl_Verts[2*i+0].normal.y = (float)1;
cyl_Verts[2*i+0].normal.z = (float)1;

cyl_Verts[2*i+1].y = -(extendMapValue*.8f) * sinf(cylTheta-theta+(D3DX_PI/2))+WIDTH/4;
cyl_Verts[2*i+1].x = (extendMapValue*.8f) * cosf(cylTheta-theta+(D3DX_PI/2))+HEIGHT/4;
cyl_Verts[2*i+1].z = 8.f;
cyl_Verts[2*i+1].color = 0xff808080;
cyl_Verts[2*i+1].u = mapStretch * (offset - ((float)i)/(cylPrec-1));
cyl_Verts[2*i+1].v = 0.0f;
cyl_Verts[2*i+1].normal.x = (float)1;
cyl_Verts[2*i+1].normal.y = (float)1;
cyl_Verts[2*i+1].normal.z = (float)1;
}

if (FAILED(p_dx_Device->CreateVertexBuffer(2*cylPrec*sizeof(OURCUSTOMVERTEX), D3DUSAGE_WRITEONLY , D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1, D3DPOOL_DEFAULT, &myCyl, NULL))){
MessageBox(han_Window,"Error while creating VertexBuffer","SetUpBackground()",MB_OK);
}

VOID* p_Vertices;
if (FAILED(myCyl->Lock(0, 2*cylPrec*sizeof(OURCUSTOMVERTEX), (void**)&p_Vertices, 0))){
MessageBox(han_Window,"Error trying to lock","SetUpBackground()",MB_OK);
}else{
memcpy(p_Vertices, cyl_Verts, 2*cylPrec*sizeof(OURCUSTOMVERTEX));
myCyl->Unlock();
}
delete [] cyl_Verts;
}






a lot of my directX data are global vars (not pretty, but i'll fix that later; i know its not whats causing the porblems)

anyways, how would i set the pointers to null on initialization? you mean something like

LPDIRECTINPUT8 inputObject;
&inputObject = NULL;

then make the inputObject?

Share this post


Link to post
Share on other sites
What I was suggesting is:

// initialization
LPDIRECT3DVERTEXBUFFER9 p_dx_VB = NULL;
LPDIRECT3DINDEXBUFFER9 p_dx_IB = NULL;
...
// in a loop somewhere
RELEASE(p_dx_VB);
RELEASE(p_dx_IB);
pDevice->CreateVertexBuffer(...,&p_dx_VB);
...
pDevice->CreateIndexBuffer(...,&p_dx_IB);
...


I'm not sure where myCyl enters the picture (it's not in the globals) but it might help to have something like:

// initialize
LPDIRECT3DVERTEXBUFFER9 myCyl = NULL;
...
void SetupBackground(...)
{
RELEASE(myCyl);
...
pDevice->CreateVertexBuffer(...,&myCyl);
...
}

With the RELEASE macro, you don't need "if(myCyl != NULL) RELEASE(myCyl);" as the macro includes "if(myCyl != NULL)". That assumes you initialize myCyl to NULL.

Also, it's good practice to clear the window inputs before you render.

while( app_running ) {
if( PeekMessage(..) ) {
// process message
} else { // do DirectX stuff only when messages are clear
// do DirectX stuff
}
}

Share this post


Link to post
Share on other sites
actually it was in my globals, being initialized to NULL as you just said. Meanwhile, the RELEASE(myCyl) and p_dx_Buffer->Create..(...&myCyl) are also already in SetupBackground, just near the start and end of the function.

(p_dx_VB and p_dx_IB are not being constantly remade, however)


I think i might just start stripping away code until i can get it running without a leak, then slowly add things to try and really pinpoint what I'm doing wrong.

Share this post


Link to post
Share on other sites
Quote:
actually it was in my globals

It's a little difficult to help diagnose code without seeing it! [wink]

Share this post


Link to post
Share on other sites
sorry about that. this is what it looks like right now

http://rafb.net/p/txHtF921.html


its pretty long.

Share this post


Link to post
Share on other sites
Still looking through the code, but noticed you "malloc" the Texture array and then "delete []" it. malloc should be paired with "free," not delete. Not sure what the effect of that is.

EDIT: you do the same with several variables. You should either "free(pointer)" or change the allocation to "new."

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!