I posted a while back ago on making directx work in classes. I'm having more issues now. On line 125 (system.cpp), when in debugging, it tells me that it has an access violation. I googled the issue, and someone had said something about initializing the pointer, but that is taken care of in d3d->CreateDevice. If anyone could help me out here, that would be great. Here's my code:
SYSTEM.CPP

#include "system.h"

//////////////////////////////////////////////////
// Class: System
// Private
//////////////////////////////////////////////////

void System::initD3D (void) {
    this->d3d = Direct3DCreate9(D3D_SDK_VERSION);

    ZeroMemory(&(this->d3dpp), sizeof(d3dpp));
    this->d3dpp.Windowed = WINDOWED;
	this->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	this->d3dpp.hDeviceWindow = this->window;
	this->d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	this->d3dpp.BackBufferWidth = SCREEN_WIDTH;
	this->d3dpp.BackBufferHeight = SCREEN_HEIGHT;
	this->d3dpp.EnableAutoDepthStencil = TRUE;
	this->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

	this->d3d->CreateDevice(D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		this->window,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&(this->d3dpp),
		&(this->d3ddev));

	d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);
	d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
};

void System::cleanD3D (void) { 
    this->d3d->Release();
    this->d3ddev->Release();
};

void System::setUpHWND (
                        HINSTANCE hInstance,
				        LPSTR lpCmdLine,
				        int nCmdShow) {
    this->hInstance = hInstance;
    this->lpCmdLine = lpCmdLine;
    this->nCmdShow = nCmdShow;

    ZeroMemory(&(this->windowClass), sizeof(WNDCLASSEX));
    this->windowClass.cbSize = sizeof(WNDCLASSEX);
    this->windowClass.style = CS_HREDRAW | CS_VREDRAW;
    this->windowClass.lpfnWndProc = System::StaticWindowProc;
    this->windowClass.hInstance = this->hInstance;
    this->windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	this->windowClass.lpszClassName = "WindowClass";
    RegisterClassEx(&(this->windowClass));

    this->window = CreateWindowEx(NULL, "WindowClass", "The Direct3D Program", 
        WS_OVERLAPPEDWINDOW, SCREEN_X, SCREEN_Y, SCREEN_WIDTH, SCREEN_HEIGHT,
        NULL, NULL, this->hInstance, NULL);
};

LRESULT CALLBACK System::StaticWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    System *SystemPtr = (System*)GetWindowLong(hWnd, GWLP_USERDATA);
 
    if(SystemPtr)
    {
        return SystemPtr->WindowProc(hWnd, message, wParam, lParam);
    }
    else
    {
       return DefWindowProc(hWnd, message, wParam, lParam);
    }
};

LRESULT System::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);
};

//////////////////////////////////////////////////
// Class: System
// Public
//////////////////////////////////////////////////

/*
System::System (void) {
    this->setUpHWND(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow);
};
*/
System::System (void) {
};

System::System (
                HINSTANCE hInstance,
                LPSTR lpCmdLine,
                int nCmdShow) {
    this->setUpHWND(hInstance, lpCmdLine, nCmdShow);

	ShowWindow(this->window, this->nCmdShow);

    this->initD3D();
};

System::System (const System &) {
};

System::~System (void) {
    this->cleanD3D();
};

void System::renderFrame (void) {
    // Update the camera here

    // Update objects

    // Clear objects

    // FOR SOME REASON THERE IS AN ERROR HERE
    this->d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);
	this->d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

	this->d3ddev->BeginScene();

    // Draw objects

    // Finish up
    this->d3ddev->EndScene(); 

	this->d3ddev->Present(NULL, NULL, NULL, NULL);
};

main.cpp

#include "system.h"

int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine,
                   int nCmdShow) {
    System MainSys;
    MainSys = System(hInstance, lpCmdLine, nCmdShow);

    // 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;

		MainSys.renderFrame();
	}

	// Clean up DirectX and the COM
	//delete MainSys;

	return msg.wParam;
};

If you need system.h, let me know

Dani AI

Generated

Good find, — the symptom you saw (access violation when calling d3ddev->Clear) is classic for “dangling COM pointers after a temporary object was destroyed.” What happened: you default-constructed MainSys, then assigned a temporary System(...) into it. The temporary’s destructor ran and released the COM pointers that had been shallow-copied into MainSys, leaving MainSys with invalid pointers. That explains why the crash went away when you stopped creating the extra instance.

Practical fixes (pick one):

  • Construct in place instead of assigning a temporary:

    System MainSys(hInstance, lpCmdLine, nCmdShow);
  • Or allocate and manage on the heap:

    auto mainSys = std::make_unique<System>(hInstance, lpCmdLine, nCmdShow);
    mainSys->renderFrame();

Design hardening and safety checks you should add:

  • If your class owns COM resources, either implement the Rule of Three/Five correctly or explicitly disable copying:

    System(const System&) = delete;
    System& operator=(const System&) = delete;
  • Use smart COM wrappers (WRL::ComPtr or CComPtr) so Release() happens automatically.

  • Never assume Direct3DCreate9 or CreateDevice succeeded — check the return value and check pointers before using them:

    HRESULT hr = d3d->CreateDevice(..., &d3ddev);
    if (FAILED(hr) || !d3ddev) { /* handle failure */ }
  • Guard releases and null out pointers after releasing:

    if (d3ddev) { d3ddev->Release(); d3ddev = nullptr; }
    if (d3d)    { d3d->Release();    d3d = nullptr; }

Window/message routing notes: make sure you store this on the window right after creating it and use the pointer variants for 64-bit safety:

SetWindowLongPtr(this->window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
System* p = reinterpret_cast<System*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

Finally, always check d3ddev before calling BeginScene, Clear, etc. These steps will prevent the dangling-pointer crash and make the class robust for future changes.

Fixed the problem, never mind. Just had to call System, instead of making two instances of it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.