releasing the d3d interfaces in a class destructor

Started by
8 comments, last by MJP 15 years, 6 months ago
Ok heres the thing, im making a d3d class that will handle pretty much anything to do with d3d. I thought it was a clever idea to initialize and shutdown d3d in the class' constructor and destructor. At first it looked like it worked but when i close the window i get an error basicly telling me that the d3d interfaces in the destructor cannot be released. so whats the deal here? is it not possible? Thanks in adv. EDIT: heres the bodies of my class (c_DIRECT3D) constructor and destructor -
c_DIRECT3D::c_DIRECT3D(s_GAMEWINDOW *gw)
{
	d3d	= Direct3DCreate9(D3D_SDK_VERSION);

	D3DPRESENT_PARAMETERS	d3dpp;
	RtlZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed		= TRUE;
	d3dpp.SwapEffect	= D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow	= gw->hwnd;

	d3d->CreateDevice(
			D3DADAPTER_DEFAULT,
			D3DDEVTYPE_HAL,
			gw->hwnd,
			D3DCREATE_SOFTWARE_VERTEXPROCESSING,
			&d3dpp,
			&d3ddev);
}

c_DIRECT3D::~c_DIRECT3D(void)
{
	d3ddev->Release();
	d3d->Release();
}

~Reegan [Edited by - Reegan on October 20, 2008 8:42:18 PM]
Advertisement
There doesn't seem to be anything wrong with the code you've posted. Have you verified that your destructor is only getting run once? Are you Releasing those interfaces anywhere else?

You also might want to consider using a smart pointer class to manage the lifetime of COM objects. IF you have access to ATL CComPtr works very well, otherwise you can use boost smart pointers with a bit of customization.
Are all Direct3d resources released properly? Direct3d might refuse to get released if there are still allocated resources.

Also, are you destroying the HWND before Direct3d gets released?

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Quote:Original post by Reegan
Ok heres the thing, im making a d3d class that will handle pretty much anything to do with d3d.
I thought it was a clever idea to initialize and shutdown d3d in the class' constructor and destructor. At first it looked like it worked but when i close the window i get an error basicly telling me that the d3d interfaces in the destructor cannot be released. so whats the deal here? is it not possible?

Thanks in adv.

EDIT: heres the bodies of my class (c_DIRECT3D) constructor and destructor -
*** Source Snippet Removed ***

~Reegan
Ok - what's the exact error? Is it a crash? Is it a message from the Debug Runtimes? A message box that your app is displaying? Something else?

And how are you handling Direct3DCreate9 or CreateDevice failing? Currently you're ignoring the return value completely, and just assuming that it works - that's going to cause you all manner of problems at some point, I can guarantee it. For instance, if CreateDevice fails in that code you've posted, you'll get an access violation when you release the device in the destructor.
@Evil Steve:-
Ok , the error is an access violation so this means that my pointer to the direct3d device (d3ddev) is being created properly right? or its failing.
im currently not handling any d3d failures as you can see, because i dont know how to stop execution of a constructor

@Endurion:-
There are no other resources than the ones you see in my destructor, im just trying to get the class to initialize and shutdown first, I know the hwnd is being destroyed but i dont know about in which order..

@MJP:- hmm.. i know nothing about "smart pointers" and how they can help me


EDIT: i found the problem, my d3d class was constructing before the window therefor the values for hwnd and all sorts were set to NULL, meaning my d3d was failing in initialization.

if someone could tell me how to stop execution of code in constructor i wouldbe greatful (usually i would just use return from a normal function).
Quote:Original post by Reegan
EDIT: i found the problem, my d3d class was constructing before the window therefor the values for hwnd and all sorts were set to NULL, meaning my d3d was failing in initialization.

if someone could tell me how to stop execution of code in constructor i wouldbe greatful (usually i would just use return from a normal function).
First, you should check the return values of ALL DirectX functions that return a pointer or other data you rely on, otherwise if the function fails and you don't notice you'll run into problems like this.
Secondly, you can't return from a constructor - the only way to break out is to throw an exception. The other alternative would be to have an initialise() function that you need to call - that function could return an error code if it fails.
Quote:Original post by Evil Steve
Secondly, you can't return from a constructor - the only way to break out is to throw an exception.

Sure you can. You can't return a value, but you can use a return statement like you would in a function with a void return type.
Quote:Original post by SiCrane
Quote:Original post by Evil Steve
Secondly, you can't return from a constructor - the only way to break out is to throw an exception.

Sure you can. You can't return a value, but you can use a return statement like you would in a function with a void return type.
Bah [smile]

Ok, I should have said "You can't return a value from a constructor - the only way to signal an error is by throwing an exception" [smile]
Actually that's not quite right either; you could set a member variable as an error flag.
Ah, thank you for your replies.
Heres the new code with error checking:

c_DIRECT3D::c_DIRECT3D(s_GAMEWINDOW *gw){	if (NULL == (d3d = Direct3DCreate9(D3D_SDK_VERSION))) {		MessageBox(NULL, "Failed to create Direct3D COM object \'d3d\'",			"D3D ERROR!", MB_ICONERROR | MB_OK);		return;	}		D3DPRESENT_PARAMETERS	d3dpp;	RtlZeroMemory(&d3dpp, sizeof(d3dpp));	d3dpp.Windowed		= TRUE;	d3dpp.SwapEffect	= D3DSWAPEFFECT_DISCARD;	d3dpp.hDeviceWindow	= gw->hwnd;	if (FAILED(d3d->CreateDevice(			D3DADAPTER_DEFAULT,			D3DDEVTYPE_HAL,			gw->hwnd,			D3DCREATE_SOFTWARE_VERTEXPROCESSING,			&d3dpp,			&d3ddev))){		MessageBox(NULL, "Failed to create the Direct3D device COM object \'d3ddev\'", 			"D3D ERROR!", MB_ICONERROR | MB_OK);		return;	}}c_DIRECT3D::~c_DIRECT3D(void){	if (d3ddev!=NULL)d3ddev->Release();	if (d3d!=NULL)d3d->Release();}


Is this good enough?
A smart pointer is an class that automatically manages the lifetime of a dynamically allocated object. Typically when a smart pointer goes out of scope, it will destroy the object it's managing.

Take this simple example with CComPtr:

void DoSomething(){    CComPtr<IDirect3DSurface9> renderTarget;    d3dDevice->GetRenderTarget(0, &renderTarget);      // Do some stuff}


What happens here is when you pass renderTarget to GetRenderTarget, the D3D device will set renderTarget to point to a surface and increment the reference count by calling AddRef. Then later when the function finishes, renderTarget goes out of scope. When this happens, CComPtr automatically calls Release so that the reference count is properly decremented.

This topic is closed to new replies.

Advertisement