Jump to content
  • Advertisement
Sign in to follow this  
deathknight2005

GameEngine - Graphics Core Error! (NULL pointer)

This topic is 4329 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 am attempting to make a full game engine, I have so far made the one part of the engine that handles the windows stuff and now I am starting on the massive graphics engine, I have very little code but so far I have one strange error that occurs at the end of the program after I exit (also the program won't go in full screen mode) This is my code for GraphicsCore.cpp:
#include "GraphicsCore.h"
void renderFrame();

GraphicsCore::GraphicsCore(HWND hwnd, bool windowed, bool depth, int red, int green, int blue, int width, int height)
{
	fullscreen = !windowed;
	depthed = depth;
	cred = red;
	cblue = blue;
	cgreen = green;
	d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
	D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
	d3dpp.Windowed = windowed;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 
	d3dpp.hDeviceWindow = hwnd;
	if (depth == true) {
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_A8R8G8B8;
	}
	d3dpp.BackBufferCount = 1;
	d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
	d3dpp.BackBufferHeight = height;
	d3dpp.BackBufferWidth = width;
    
    d3d9->CreateDevice(D3DADAPTER_DEFAULT,
                       D3DDEVTYPE_HAL,
                       hwnd,
                       D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                       &d3dpp,
                       &d3ddev);

}
void GraphicsCore::renderD3D()
{
	if(depthed == true) 
	   d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    
	d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(cred, cgreen, cblue), 1.0f, 0);
    d3ddev->BeginScene();
    renderFrame();
    d3ddev->EndScene();   
	d3ddev->Present(NULL, NULL, NULL, NULL);    
}
void GraphicsCore::escapeButton(HWND hwnd)
{
if(KEY_DOWN(VK_ESCAPE))
    PostMessage(hwnd, WM_DESTROY, 0, 0); 
}
GraphicsCore::~GraphicsCore(void)
{
	d3ddev->Release();
	d3d9->Release(); //this is where the error occurs
}



Also here is some more code where I use the graphics core and windows core:
#include "GameEngine.h"
WindowsCore* wc;
GraphicsCore* gc;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	
	wc = new WindowsCore(L"Jeremy", L"Jerbear", hInstance, nShowCmd, true);
	gc = new GraphicsCore(wc->getHwnd(), false, false, 0, 0, 0);
    return wc->SetUp(640, 480);
}
void QuitQuery()//windows core
{
 wc->ShowMsgBox(L"hello", L"Hello"); //windows core
 delete wc;//windows core
 delete gc;
}
void GameLoop() //windows core
{
	gc->escapeButton(wc->getHwnd());
}
void renderFrame(){
}


And it is giving me this error message after I exit: Unhandled exception at 0x0041208f in Basic Direct.exe: 0xC0000005: Access violation reading location 0x00000000. and it is pointing to: d3ddev->Release(); I know that for some reason d3ddev is a NULL pointer but I don't know where this is happening!

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster

CreateDevice() will return an HRESULT indicating success or failure, would be worth checking, or check that the d3dDev is not null after the call. The HRESULT will pretty much let you know what went wrong, you can also turn up the debug output in D3d via the DirectX control panel, should be in the OS control panel, or if you have the october 2006 sdk, i have just noticed it is actually in the utilities section in the start menu under the DirectX 9.0 folder.

Have you stepped through the code to check the values in the RenderD3D() method?
You can also turn on breaking on exceptions, and the debugger will break on the access violation exception.

If that does not show anything up, may be worth posting your windows code.


Hope this helps.

Share this post


Link to post
Share on other sites
Do yourself a MASSIVE favour and add something like this to a globally shared header file:

#define HR_VERIFY(n) if(FAILED(n)) { assert(false); }

and wrap EVERY d3d call that returns an HRESULT with it.

e.g.

HR_VERIFY( m_pd3dDevice->Present(NULL, NULL, NULL, NULL) );

This will catch any errors immediately and save you a lot of hassle.

//----

You can also add something like:

#define SAFE_RELEASE(n) { if(n) { (n)->Release(); } }

and do release calls with it so it automatically checks against a NULL pointer

e.g.

SAFE_RELEASE(m_pD3DDevice);

same as delete and array deletion

#define SAFE_DELETE(p) { if(p) { delete p; p = NULL; } }
#define SAFE_ARRAY_DELETE(p) { if(p) { delete [] p; p = NULL; } }

it automatically checks NULL pointers and sets a pointer to NULL after deleting the object.

Hope this helps,

Wally.

:D

Share this post


Link to post
Share on other sites
Thank you for replying, I still haven't completely figured it out but it is happening in CreateDevice. I think it has something to do with the call to getHwnd, maybe it has to be a pointer to the hwnd? Anyways here is the Windows Core code:
WindowsCore.h:

#pragma once
#include <windows.h>
class WindowsCore
{
public:
WindowsCore(LPCWSTR name, LPCWSTR name2, HINSTANCE hInstance, int ShowCmd, bool fullscreen);
int SetUp(int width, int height);
void ShowMsgBox(LPCWSTR text, LPCWSTR text2);
HWND getHwnd(){return hwnd; }
protected:
HWND hwnd;
HINSTANCE hInstance;
int nShowCmd;
bool fullscr;
LPCWSTR className, windowName;
};



And here is WindowsCore.cpp:

#include "WindowsCore.h"
LRESULT CALLBACK WindowProc(HWND hWnd,UINT message,WPARAM wParam, LPARAM lParam);
void QuitQuery();
void GameLoop();
WindowsCore::WindowsCore(LPCWSTR name, LPCWSTR name2, HINSTANCE hInst, int ShowCmd, bool fullscreen)
{
className = name;
windowName = name2;
hInstance = hInst;
nShowCmd = ShowCmd;
fullscr = fullscreen;
}
int WindowsCore::SetUp(int width, int height)
{
MSG msg;
WNDCLASSEX wce;
ZeroMemory(&wce, sizeof(WNDCLASSEX));
wce.cbSize = sizeof(WNDCLASSEX);
if (fullscr == false) {
wce.hbrBackground = (HBRUSH)COLOR_WINDOW;
}
wce.hCursor = LoadCursor(hInstance, IDC_ARROW);
wce.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wce.hInstance = hInstance;
wce.lpfnWndProc = WindowProc;
wce.lpszClassName = className;
wce.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wce);
if (fullscr == true){
hwnd = CreateWindowEx(NULL, className, windowName, WS_EX_TOPMOST | WS_POPUP, 0, 0, width, height, NULL, NULL, hInstance, NULL);
}
hwnd = CreateWindowEx(NULL, className, windowName, WS_OVERLAPPEDWINDOW, 0, 0, width, height, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nShowCmd);
while(TRUE)
{
DWORD starting_point = GetTickCount();
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}

GameLoop();
while ((GetTickCount() - starting_point) < 25);
}
return msg.wParam;
}
void WindowsCore::ShowMsgBox(LPCWSTR text, LPCWSTR text2)
{
MessageBox(hwnd, text, text2, 0);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
QuitQuery();
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}



Share this post


Link to post
Share on other sites
Guest Anonymous Poster

Ok the reason is that when you create the device the window has not been setup, so the window handle is invalid.

You need to call CreateWindowEx before you create the device so you have a valid window handle, you can then show and update the window before you enter the message pump / game loop.



Share this post


Link to post
Share on other sites
Thank you for the help, and now that error is not a problem anymore but I've uncovered another error that is basically the same thing and for some reason it is not working! This is the error:
Unhandled exception at 0x00414380 in Basic Direct.exe: 0xC0000005: Access violation reading location 0x00000008.
And it is pointing at the d3ddev->Clear() line of code. Because I actually called the render function now but for some reason it is messing up again on another d3ddev function!
Edit: I have now decided to put the GraphicsCore and WindowsCore together to make one big class called GameEngine I am still having the error though:
Here is GameEngine.h:

#pragma once
#include <windows.h>
#include <d3d9.h>
#pragma comment (lib, "d3d9.lib")
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define HR_VERIFY(n) if(FAILED(n)) { MessageBox(NULL, L"Error Occured", L"Error", 0); }
#define SAFE_RELEASE(n) { if(n) { (n)->Release(); } }
class GameEngine
{
public:
//Constructor / Destructor
GameEngine(LPCWSTR name, LPCWSTR name2, HINSTANCE hInst, int ShowCmd, bool fullscreen, bool depth, int red, int green, int blue, int swidth, int sheight);//

//windows
int SetUp();//
void ShowMsgBox(LPCWSTR text, LPCWSTR text2);//
HWND getHwnd(){return hwnd; } //
//Graphics
bool returnFullScreen() { return fullscr? true : false; }//
void render_frame();//
private:
//windows
HWND hwnd;//
HINSTANCE hInstance;//
int nShowCmd;//
LPCWSTR className, windowName;//
//graphics
LPDIRECT3D9 d3d;//
LPDIRECT3DDEVICE9 d3ddev;//
int cred, cgreen, cblue;//
bool fullscr;//
bool depthed;//
void initD3D();//
void cleanD3D();//
int width, height;
};



Here is GameEngine.cpp:

#include "GameEngine.h"
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void userRender();
void QuitQuery();
GameEngine::GameEngine(LPCWSTR name, LPCWSTR name2, HINSTANCE hInst, int ShowCmd, bool fullscreen,bool depth, int red, int green, int blue, int swidth = 640, int sheight = 480)
{
className = name;
windowName = name2;
hInstance = hInst;
nShowCmd = ShowCmd;
fullscr = fullscreen;
depthed = depth;
cred = red;
cblue = blue;
cgreen = green;

}
int GameEngine::SetUp()
{

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);
// wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // not needed any more
wc.lpszClassName = className;

RegisterClassEx(&wc);

hwnd = CreateWindowEx(NULL,
className,
windowName,
WS_EX_TOPMOST | WS_POPUP, // fullscreen values
0, 0, // the starting x and y positions should be 0
width, height, // set the window to 640 x 480
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hwnd, nShowCmd);

// set up and initialize Direct3D
initD3D();

// enter the main loop:

MSG msg;

while(TRUE)
{
DWORD starting_point = GetTickCount();

if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}

render_frame();

// check the 'escape' key
if(KEY_DOWN(VK_ESCAPE))
PostMessage(hwnd, WM_DESTROY, 0, 0);

while ((GetTickCount() - starting_point) < 25);
}

// clean up DirectX and COM
cleanD3D();

return msg.wParam;
}
void GameEngine::initD3D()
{
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 = FALSE; // program fullscreen, not windowed
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames
d3dpp.hDeviceWindow = hwnd; // set the window to be used by Direct3D
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; // set the back buffer format to 32-bit
d3dpp.BackBufferWidth = width; // set the width of the buffer
d3dpp.BackBufferHeight = height; // set the height of the buffer


// create a device class using this information and the info from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);

}
void GameEngine::cleanD3D()
{
SAFE_RELEASE(d3d);
SAFE_RELEASE(d3ddev);
}
void GameEngine::render_frame()
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(cred, cgreen, cblue), 1.0f, 0);

d3ddev->BeginScene(); // begins the 3D scene

userRender();

d3ddev->EndScene(); // ends the 3D scene

d3ddev->Present(NULL, NULL, NULL, NULL); // displays the created frame on the screen
}
void GameEngine::ShowMsgBox(LPCWSTR text, LPCWSTR text2)
{
MessageBox(hwnd, text, text2, 0);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
QuitQuery();
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}



Here is WinMain.cpp:

#include "GameEngine.h"
GameEngine* ge;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
ge = new GameEngine(L"Jeremy", L"Lord", hInstance, nCmdShow, true, false, 0, 0, 0, 640, 480);
ge->SetUp();

}
void userRender()
{
}
void QuitQuery()
{
}


Here is the error message:
Unhandled exception at 0x00411a22 in Game Engine.exe: 0xC0000005: Access violation reading location 0x00000000.
And it is still on the line: d3ddev->Clear();
can someone please help!

[Edited by - deathknight2005 on November 17, 2006 5:12:22 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster

Ok the problem is you are not setting the width and height, so the values used in the presentation parameters are uninitialised and a number like -3545534343, so the create device is failing. Add the assignments in your constructor:

width = swidth;
height = sheight;

But you are still not checking your return values, i.e.

HRESULT hr = CreateDevice(&d3dDev);
if((FAILED(hr) || (d3dDev == NULL))
MessageBox("Failed to create device");
else
MessageBox("Successfully created device");

You have created the verify macro, use it.

Think you need to brush up on your debugging skills ;-) Step through the code and look at each variable to make sure it is what you expect, also turn on the D3D debug runtime, this will spew out useful information if something is amiss.

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!