Jump to content
  • Advertisement
Sign in to follow this  
yo1dog

Pos resource leak? - Solved

This topic is 3320 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

I created this simple DirectX program in VC++. It simulates a grid with moving nodes. Basically like the grid on Geometry Wars. The problem is that it will either crash or become very slow at random times while moving the grid around and I am wondering if this is because of a resource leak. On a side note, nothing keeps the nodes from going way off the screen if that may be a problem. Here is the compiled program and the code: EXE: http://host-a.net/yo1dog/DirectX_GRID.zip
// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <Math.h>
#include <d3d9.h>
#include <d3dx9.h>

#define WINDOWED false

// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

// global declarations
LPDIRECT3D9 d3d;	// the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev;    // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;    // the pointer to the vertex buffer
LPD3DXFONT dxfont;    // the pointer to the font object

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) 

// define the screen resolution
#define SCREEN_WIDTH  ((WINDOWED)? 800 : 1680)
#define SCREEN_HEIGHT ((WINDOWED)? 600 : 1050)

#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
struct Vertex
{
    float x, y, z, rhw;    // from the D3DFVF_XYZRHW flag
    DWORD color;    // from the D3DFVF_DIFFUSE flag
};

// function prototypes
void initD3D(HWND hWnd);    // sets up and initializes Direct3D
void render_frame(void);    // renders a single frame
void cleanD3D(void);    // closes Direct3D and releases memory
void init_graphics(void);    // 3D declarations

void init(void);
void run(void);
void updateVertices(void);
void createExplotion(float, float, float, int);
void createImplotion(float, float, float, int);

//===================================================
#define WIDTH	SCREEN_WIDTH
#define HEIGHT	SCREEN_HEIGHT
#define s	20
#define w	(int)(WIDTH/s + 1)
#define h	(int)(HEIGHT/s + 1)
#define n	w*h
#define nl	((w - 1)*2*h + (h - 1)*2*w + 8 + w*4 + h*4)
//			 |		inner            |   |   outer    |

#define ELASTIC		0.2
#define FRICTION	0.1

float grid[n][4];	//Position   0: X Pos,  1: Y Pos,  2: Orig X Pos,  3: Orig Y Pos
bool gridA[n];		//Active (run calculations)
float gridT[n];		//Angle of motion
float gridV[n][3];	//Velocity   0: X Vel,  1: Y Vel,  2: Vel
int gridC[n][4];	//Color   0: Red,  1: Blue,  2: Green,  3: Alpha

#define gridColor D3DCOLOR_ARGB(0, 0, 255, 0)

Vertex vertices
; #define XOFFSET (int)((SCREEN_WIDTH - WIDTH)/2); #define YOFFSET (int)((SCREEN_HEIGHT - HEIGHT)/2); int mx = 0, my = 0; //=================================================== // the WindowProc function prototype LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // the entry point for any Windows program int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hWnd; WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); if (WINDOWED) wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszClassName = (LPCSTR)"WindowClass"; RegisterClassEx(&wc); if (WINDOWED) hWnd = CreateWindowEx(NULL, (LPCSTR)"WindowClass", (LPCSTR)"Our First Direct3D Program", WS_OVERLAPPEDWINDOW, 300, 300, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL); else hWnd = CreateWindowEx(NULL, (LPCSTR)"WindowClass", (LPCSTR)"Our First Direct3D Program", WS_EX_TOPMOST | WS_POPUP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); init(); // set up and initialize Direct3D initD3D(hWnd); // enter the main loop: MSG msg; while(true) { while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } if(msg.message == WM_QUIT) break; POINT cursorPos; GetCursorPos(&cursorPos); mx = cursorPos.x - XOFFSET; my = cursorPos.y - YOFFSET; //Render a frame render_frame(); // check the 'escape' key if (KEY_DOWN(VK_ESCAPE)) PostMessage(hWnd, WM_DESTROY, 0, 0); } // clean up DirectX and COM cleanD3D(); return msg.wParam; } // this is the main message handler for the program LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_DESTROY: { PostQuitMessage(0); return 0; } break; } return DefWindowProc (hWnd, message, wParam, lParam); } // this function initializes and prepares Direct3D for use void initD3D(HWND hWnd) { d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use d3dpp.Windowed = WINDOWED; // program windowed, not fullscreen d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames d3dpp.hDeviceWindow = hWnd; // set the window to be used by Direct3D //Fullscreen d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; // set the back buffer format to 32-bit d3dpp.BackBufferWidth = SCREEN_WIDTH; // set the width of the buffer d3dpp.BackBufferHeight = SCREEN_HEIGHT; // set the height of the buffer // create a device class using this information and information from the d3dpp stuct d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev); //create font class D3DXCreateFont(d3ddev, // the D3D Device 24, // font height of 30 0, // default font width FW_BOLD, // font weight 1, // not using MipLevels false, // italic font DEFAULT_CHARSET, // default character set OUT_DEFAULT_PRECIS, // default OutputPrecision, DEFAULT_QUALITY, // default Quality DEFAULT_PITCH | FF_DONTCARE, // default pitch and family (LPCSTR)"Arial", // use Facename Arial &dxfont); // the font object //no ambient light (NEW) d3ddev->SetRenderState(D3DRS_AMBIENT,RGB(0,0,0)); //lighting enabled (NEW) d3ddev->SetRenderState(D3DRS_LIGHTING,true); d3ddev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); d3ddev->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE); } // this is the function used to render a single frame void render_frame(void) { // clear the window to a deep blue d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); run(); updateVertices(); init_graphics(); d3ddev->BeginScene(); // begins the 3D scene // do 3D rendering on the back buffer here // select which vertex format we are using d3ddev->SetFVF(CUSTOMFVF); // select the vertex buffer to display d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(Vertex)); // copy the vertex buffer to the back buffer d3ddev->DrawPrimitive(D3DPT_LINELIST, 0, nl/2); // create a RECT to contain the text static RECT textbox; SetRect(&textbox, 0, 0, 640, 480); // draw the Hello World text dxfont->DrawTextA(NULL, "Space - Create Explotion\nCtrl - Create Implotion\nI - Hide this\nHold Shift to amplify effect", 91, &textbox, DT_LEFT | DT_TOP, D3DCOLOR_ARGB(200, 255, 0, 0)); d3ddev->EndScene(); // ends the 3D scene d3ddev->Present(NULL, NULL, NULL, NULL); // displays the created frame } // this is the function that cleans up Direct3D and COM void cleanD3D(void) { v_buffer->Release(); // close and release the vertex buffer d3ddev->Release(); // close and release the 3D device d3d->Release(); // close and release Direct3D } void init_graphics(void) { // create the vertex and store the pointer into v_buffer, which is created globally d3ddev->CreateVertexBuffer(nl*sizeof(Vertex), 0, CUSTOMFVF, D3DPOOL_MANAGED, &v_buffer, NULL); VOID* pVoid; // the void pointer v_buffer->Lock(0, 0, (void**)&pVoid, 0); // lock the vertex buffer memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer v_buffer->Unlock(); // unlock the vertex buffer } void init(void) { for (int y=0; y < h; y++) { for (int x=0; x < w; x++) { int i = x + y*w; grid[0] = x*s; //X pos grid[1] = y*s; //Y pos grid[2] = x*s; //Original X pos grid[3] = y*s; //Original Y pos gridA = false; //Active gridT = 0; //Angle of motion gridV[0] = 0; //X Vel gridV[1] = 0; //Y Vel gridV[2] = 0; //Vel } } } void updateVertices() { //Updates vertices[] array with grid array } void run(void) { //Code for moving the nodes //only deals with the grid arrays so problem can't be here //Note: nothing keeps the nodes from going way off the screen } void createExplotion(float xx, float yy, float p, int r) { //More code for moving nodes //only deals with the grid arrays so problem can't be here } void createImplotion(float xx, float yy, float p, int r) { //More code for moving nodes //only deals with the grid arrays so problem can't be here }
[Edited by - yo1dog on May 18, 2009 7:43:15 PM]

Share this post


Link to post
Share on other sites
Advertisement
Can't really follow that much code thrown at me at once, but it sure looks like you are iterating through all your vertices and changing them every single frame. That can't be very efficient at all.

Are you sure your doing something you can't accomplish with a transformation matrix?

Share this post


Link to post
Share on other sites
There is indeed a resource leak. In your render_frame() function, which is called every frame, you call init_graphics(). Here, you call CreateVertexBuffer() which allocates a D3D vertex buffer - which you never release. That is, every time you call CreateVertexBuffer, you overwrite the contents of the v_buffer without releasing it (by calling Release()) - this means you have leaked memory.

The net effect is that every single frame you are allocating a large object but never releasing it.

You should call Release() on v_buffer before overwriting the pointer. Ideally, you shouldn't be creating a new vertex buffer per frame anyway - that's bound to be slow. Create the vertex buffer once when you initialise D3D - and just reuse the same buffer. The size of your vertex buffer doesn't change, so there's no need to constantly recreate it.

Also: Don't mix spaces and tabs! Pick one and stick to it - your code indentation is all over the place.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sc4Freak
There is indeed a resource leak. In your render_frame() function, which is called every frame, you call init_graphics(). Here, you call CreateVertexBuffer() which allocates a D3D vertex buffer - which you never release. That is, every time you call CreateVertexBuffer, you overwrite the contents of the v_buffer without releasing it (by calling Release()) - this means you have leaked memory.

The net effect is that every single frame you are allocating a large object but never releasing it.

You should call Release() on v_buffer before overwriting the pointer. Ideally, you shouldn't be creating a new vertex buffer per frame anyway - that's bound to be slow. Create the vertex buffer once when you initialise D3D - and just reuse the same buffer. The size of your vertex buffer doesn't change, so there's no need to constantly recreate it.

Also: Don't mix spaces and tabs! Pick one and stick to it - your code indentation is all over the place.


I think I follow what you mean... This was my first attempt at DirectX as you can probably tell.

As for the spaces and tabs, VC++ can be weird sometimes and turns my tabs into spaces. I will clean that up.

Share this post


Link to post
Share on other sites
OK, so I got rid of the init_graphics method, Created the buffer in the init_D3D method, and wrote to the buffer at the end of the updateVertices method.

So I create the buffer once and rewrite it every frame.

Thanks for the help!

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!