Destructor crashing game?
#1 Members - Reputation: 102
Posted 26 September 2011 - 11:50 AM
D3DMATERIAL9* mmaterial;
LPDIRECT3DTEXTURE9* ttexture;
as global variables that are used for loading in meshs and what not.
Whenever I close the program I get memory leaks from them as they are not being destroyed.
So simple enough I just make a destructor and in it I put
delete[] mmaterial;
delete[] ttexture;
inside of it
When I start up my game it crashes the game and visual studio. And I'm not particularly sure why...
my destructor looks like this
Ship::~Ship()
{
delete[] mmaterial;
delete[] ttexture;
}
Any insight or links to other articles would be helpful =)
or atleast what to search for since it seems apparently I can't find anything
Thanks
#2 Members - Reputation: 191
Posted 26 September 2011 - 02:19 PM
#3 Members - Reputation: 109
Posted 26 September 2011 - 02:26 PM
delete[] mmaterial;
delete[] ttexture;
Why this? Your data members are declared as:
D3DMATERIAL9* mmaterial;
LPDIRECT3DTEXTURE9* ttexture;
You do not have an array of them, just a pointer to them. Try to remove the brackets [ ].
Abstraction is my choice of words.
Portfolio: http://www.0x3a.com/
Blog: http://blog.0x3a.com/
#4 Moderators - Reputation: 6640
Posted 26 September 2011 - 02:37 PM
In C++ a pointer to a single element and a pointer to an array of elements have the same type. You can't know without seeing how it's used which a pointer is pointing to.You do not have an array of them, just a pointer to them. Try to remove the brackets [ ].
#5 Members - Reputation: 191
Posted 26 September 2011 - 02:39 PM
You do not have an array of them, just a pointer to them. Try to remove the brackets [ ].
I agree for the first one (D3DMATERIAL9). However LPDIRECT3DTEXTURE9 is a definition of a pointer to a DIRECT3DTEXTURE9 structure. However I'm a bit rusty with C++ and I'm not sure how the delete operator works with typedefs
EDIT : Well, SiCrane must know better than me ;)
#6 Members - Reputation: 102
Posted 26 September 2011 - 02:48 PM
Use
delete[] mmaterial; (if its an array)
ttexture->Release();
instead.
or even better:
if(mmaterial != NULL)
delete[] mmaterial;
if(ttexture != NULL)
ttexture->Release();
with that, youll also have to set the pointers to null in the ctor:
Ship::Ship()
{
mmaterial = NULL;
ttexture = NULL;
}
with that, if something happens and the stuff never gets allocated, it wont crash since the pointer has not changed from NULL.
#7 Members - Reputation: 109
Posted 26 September 2011 - 03:11 PM
In C++ a pointer to a single element and a pointer to an array of elements have the same type. You can't know without seeing how it's used which a pointer is pointing to.
You do not have an array of them, just a pointer to them. Try to remove the brackets [ ].
True, but seeing he had a crash and his data is, hopefully, correct it could be the case.
Abstraction is my choice of words.
Portfolio: http://www.0x3a.com/
Blog: http://blog.0x3a.com/
#8 Members - Reputation: 880
Posted 26 September 2011 - 05:20 PM
#9 Moderators - Reputation: 6640
Posted 26 September 2011 - 08:26 PM
The delete operator doesn't care about typedefs, it just looks at the actual type. In the case of an LPDIRECT3DTEXTURE9 *, that would be a Direct3DTexture9 **. This could either be a pointer to a Direct3DTexture9 pointer or a pointer to an array of pointers.However I'm a bit rusty with C++ and I'm not sure how the delete operator works with typedefs
There is a difference between saying "this could be the cause of your crash" and "this is the cause of your crash". Please observe this distinction when making future posts.True, but seeing he had a crash and his data is, hopefully, correct it could be the case.
In theory, it could. Using the wrong delete or delete [] has undefined behavior, which means anything can happen, including an access violation on that read. However, it's not guaranteed. For an access violation to occur on that read, the memory in that location would need to lack read permission, and, in practice, most memory allocators place other bookkeeping structures in front of allocated blocks, so that particular read rarely causes an access violation by itself. Acting on the information in the memory, on the other hand, has much better chances of bringing down the program somehow. If the type lacks a destructor, then it's entirely possible for using delete [] instead of delete to deallocate the memory successfully. Undefined behavior means anything can happen, up to and including "working".In the case of some compilers sticking the length of an array allocated with new just before the returned pointer, wouldn't attempting to read before the block allocated for a single object cause an access violation if one uses the wrong delete?
#10 Members - Reputation: 102
Posted 27 September 2011 - 12:08 AM
Ship::Ship(LPCTSTR nameT, LPDIRECT3DDEVICE9 dDevice)
{
d3Device = dDevice;
name = nameT;
LPD3DXBUFFER bufShipMaterial;[/size]
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[/size]
// retrieve the pointer to the buffer containing the material information
D3DXMATERIAL* tempMaterials = (D3DXMATERIAL*)bufShipMaterial->GetBufferPointer();[/size]
// create a new material buffer for each material in the mesh
mmaterial = new D3DMATERIAL9[NumMaterials];
ttexture = new LPDIRECT3DTEXTURE9[NumMaterials];[/size]
for(DWORD i = 0; i < NumMaterials; i++) // for each material...
{
mmaterial[i] = tempMaterials[i].MatD3D; // get the material info
mmaterial[i].Ambient = mmaterial[i].Diffuse; // make ambient the same as diffuse
// if there is a texture to load, load it
if(FAILED(D3DXCreateTextureFromFileA(d3Device,
tempMaterials[i].pTextureFilename,
&ttexture[i])))
ttexture[i] = 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[i]->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 casePretty 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?
#11 Moderators - Reputation: 5034
Posted 27 September 2011 - 02:03 AM
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.
#12 Moderators - Reputation: 6640
Posted 27 September 2011 - 08:08 AM
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.and after reading through your comments and what not I tried using just delete vs delete[].
#13 Members - Reputation: 102
Posted 28 September 2011 - 11:58 PM
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.
#14 Moderators - Reputation: 5034
Posted 29 September 2011 - 03:01 AM
Which is it? Are these variables global, or class members?so in a class I have
D3DMATERIAL9* mmaterial;
LPDIRECT3DTEXTURE9* ttexture;
as global variables that are used for loading in meshs and what not.
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.
Destructors run at run time. They don't run at compile time, which is the usual "opposite" of run time.If its a destructor why at run time would it cause this?
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
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.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.
Show us what you've tried.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.
#15 Members - Reputation: 102
Posted 29 September 2011 - 12:43 PM
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
#16 Members - Reputation: 3814
Posted 29 September 2011 - 01:14 PM
(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[i]->Release (); textures.clear ();
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.
#17 Members - Reputation: 102
Posted 29 September 2011 - 01:57 PM
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?
#18 Members - Reputation: 3814
Posted 29 September 2011 - 03:10 PM
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.
#19 Members - Reputation: 102
Posted 02 October 2011 - 12:32 PM
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
bool checkDevice()
{
switch(g_pd3dDevice->TestCooperativeLevel())
{
case D3DERR_DEVICELOST:
{
onLostDevice();
return false;
}
case D3DERR_DEVICENOTRESET:
{
onResetDevice();
return false;
}
}
return true;
}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();
#20 Members - Reputation: 3814
Posted 02 October 2011 - 01:58 PM
The right place to call OnLostDevice is when you get D3DERR_DEVICENOTRESET; this means that the device was once lost, is not any more, but needs a reset before you can continue drawing. At that point you need to call your OnLostDevice methods, then Reset the device, then TestCooperativeLevel again until you get D3D_OK, at which point the reset has completed and you can call OnResetDevice and continue drawing.
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.






