Destructor crashing game?

Started by
18 comments, last by 21st Century Moose 12 years, 6 months ago
Ok first off Thanks for all the replies. I figure I should post all the code so you guys can have a better idea of what is happening


Ship::Ship(LPCTSTR nameT, LPDIRECT3DDEVICE9 dDevice)
{

d3Device = dDevice;
name = nameT;
LPD3DXBUFFER bufShipMaterial;

D3DXLoadMeshFromX(name, // load this file
D3DXMESH_SYSTEMMEM, // load the mesh into system memory
d3Device, // the Direct3D Device
NULL, // we aren't using adjacency
&bufShipMaterial, // put the materials here
NULL, // we aren't using effect instances
&NumMaterials, // the number of materials in this model
&Mesh); // put the mesh here

// retrieve the pointer to the buffer containing the material information
D3DXMATERIAL* tempMaterials = (D3DXMATERIAL*)bufShipMaterial->GetBufferPointer();

// create a new material buffer for each material in the mesh
mmaterial = new D3DMATERIAL9[NumMaterials];
ttexture = new LPDIRECT3DTEXTURE9[NumMaterials];

for(DWORD i = 0; i < NumMaterials; i++) // for each material...
{
mmaterial = tempMaterials.MatD3D; // get the material info
mmaterial.Ambient = mmaterial.Diffuse; // make ambient the same as diffuse
// if there is a texture to load, load it
if(FAILED(D3DXCreateTextureFromFileA(d3Device,
tempMaterials.pTextureFilename,
&ttexture)))
ttexture = NULL; // if there is no texture, set the texture to NULL
}
}

Now that is my constructor for my Ship class. All it does really is just load in the mesh I want for whichever "Ship"
I realize some is messy and I intend on cleaning on all my code once I fix all my memory leaks.

and my destructor


Ship::~Ship()
{
for(DWORD i = 0; i < NumMaterials; i++)
{
ttexture->Release();
}

delete[] ttexture;
delete[] mmaterial;
}

and after reading through your comments and what not I tried using just delete vs delete[]. In my default constructor I made both variables null just in case

Pretty much what happens is when I run game in visual studio as its loading up it freezes and freezes up visual studio to the point where I have to end process everytime.
So i'm assuming there is a memory leak that its just not liking?


Advertisement
Does your class have a copy constructor or assignment operator? Or rather, is it noncopyable or does it obey the rule of three?

Your constructor appears to lack appropriate error handling. You don't handle the case where mesh creation fails. You explicitly do handle the case where texture creation fails - but you don't account for it in your destructor. You should probably log failed texture creation. You probably want to release any resources associated with the mesh too.

and after reading through your comments and what not I tried using just delete vs delete[].

Please don't voodoo program. If you use new to allocate memory use delete to deallocate the memory. If you use new [] to allocate the memory use delete [] to deallocate the memory. Or, since it seems like you are using dynamic arrays here, use a std::vector instead of manually managing the memory and you don't need to worry about explicitly deallocating the memory.
After putting in place the proper checks and what not into the constructor and destructor as soon as I run it it acts like its on a never ending loop that cause both the program and visual studio to freeze up. This has only ever happened to me when a memory leak has happened that I just completely missed. But this time I can't see anything I'm missing. If its a destructor why at run time would it cause this? My class does not obey the rule of three. After reading up on that I couldn't imagine that being the cause of this problem.

Thanks for the replies by the way guys
this problem is frustrating.

p.s. I tried the std:vector I was able to declare the variables. But for somereason I couldn't figure out how to set the variables. i.e. mmaterial = ? I tried looking it up online but so far nothing that even remotely shows it. Maybe my searching skills need improving.
How did I miss this part:

so in a class I have
D3DMATERIAL9* mmaterial;

LPDIRECT3DTEXTURE9* ttexture;

as global variables that are used for loading in meshs and what not.
[/quote]
Which is it? Are these variables global, or class members?

If they are global, you should be initialising and cleaning them up outside the ship class. Otherwise multiple ship instances won't play nice together.


If its a destructor why at run time would it cause this?
[/quote]
Destructors run at run time. They don't run at compile time, which is the usual "opposite" of run time.

In case you though they only run when your program is shutting down, this is not the case. They run whenever an object goes out of scope, or is explicitly deleted.

void example()
{
Ship value(...);
Ship *pointer = new Ship(...);

// Do stuff

delete pointer; // pointer->~Ship() semi-implicitly called here

} // value.~Ship() implicitly called here



My class does not obey the rule of three. After reading up on that I couldn't imagine that being the cause of this problem.
[/quote]
It could be, if your class is being accidentally copied or assigned. Or if the values are global, each additional ship instance will clobber the previous values.


I tried the std:vector I was able to declare the variables. But for somereason I couldn't figure out how to set the variables. i.e. mmaterial = ? I tried looking it up online but so far nothing that even remotely shows it. Maybe my searching skills need improving.
[/quote]
Show us what you've tried.
When I said global variables I meant as they are global inside the Ship class. So when I create a new object for the class each object should have its own variables right?

I'm thinking though, when I create the object in my main class i'm doing
Ship one = Ship(insertstuff here);

and thats it. I notice some people have pointers to there objects or something of the sort. I may have that all wrong.

now that I think about it the second ship seems textures itself red for no real reason. And I know the Bi plane has red on it.

and as for my attempt I did

std::vector<D3DMATERIAL9*> mmaterial;

then tried to define it doing

mmaterial = new D3DMATERIAL9(NumMaterials);
also
mmaterial = new D3DMATERIAL9[NumMaterials];
also
mmaterial = new <D3DMATERIAL9> and thats about as far as I got on that one.

I notice in all the examples they do
std::vector<D3DMATERIAL9*> mmaterial(NumMaterials);
I'm not sure how to break that up at all though

I know its got to be absolutely simple. But for the life of me I can't figure it out

thanks for your help rip-off
For your original problem, you might want to double-check when your destructor actually runs. It sounds as though it's running after you've Released your IDirect3DDevice9 interface, which explains both the crashes and the leaks. http://blogs.msdn.com/b/oldnewthing/archive/2004/05/20/135841.aspx

(It's worth noting by the way that D3D uses COM interfaces, not C++ classes. They might look superficially similar but there is a whole world of subtle differences between them.)

For std::vector, you're going about it in a slightly convoluted manner. It's really as simple as this (untested, off the top of my head, don't copy/paste this!!!):std::vector<LPDIRECT3DTEXTURE9> textures;
LPDIRECT3DTEXTURE9 newtexture = NULL;
Device->CreateTexture (blahblahblah... &newtexture...);
textures.push_back (newtexture);

for (int i = 0; i < textures.size (); i++)
textures->Release ();

textures.clear ();

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

The program would still run correctly until shutdown time if it is being released after IDirect3DDevice9 wouldn't it? since my problem seems to be immediate on start up.

I got the vector compiling finally kinda

std::vector<LPDIRECT3DTEXTURE> ttexture;

// constructor method

LPDIRECT3DTEXTURE temp = NULL;

for loopy
createtexture(blahbluhblah... &temp);

ttexture.push_back(temp)

and it all works just fine and my texture memory leaks are now gone! YaY! Thanks mhagain
Although I'm still curious as to why my destructor hates me


also p.s. could anyone tell my whyD3DXCreateFont

creates a memory leak?
A lot of D3DX interfaces (and ID3DXFont is one of them) create other resources behind the scenes for you. These may be vertex buffers, textures, whatever. You can tell this by checking if the D3DX interface has OnLostDevice and OnResetDevice members. In these cases, always call OnLostDevice before Releasing the interface otherwise you'll leak those resources.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Ok I've finally got around to trying to implement OnLostDevice and OnResetDevice

and for some odd reason they are still leaking memory. And when I comment them out the memory errors are on so l must be doing something wrong.

i have a
bool checkDevice()
that i use when I do
if(checkDevice())
render();

so that way if something is wrong it wont try and render. I'm hoping I did that correctly and in this checkDevice its
[source]
bool checkDevice()
{
switch(g_pd3dDevice->TestCooperativeLevel())
{
case D3DERR_DEVICELOST:
{
onLostDevice();
return false;
}
case D3DERR_DEVICENOTRESET:
{
onResetDevice();
return false;
}
}
return true;
}[/source]

now I know the device reset needs some work and that was the next thing to do but for the moment onLostDevice seems to not work
onLostDevice just has
dxfont->OnLostDevice();
and so on.
I tried just calling this method right as the loop is ending before I call my release method for everything and I'm still getting memory leaks. Any idea what I could be doing wrong?
Thanks for all the help
sprite->onLostDevice();

This topic is closed to new replies.

Advertisement