C++ deleting a sprite with delete operator
Hi everyone!
I've been reading an old post from this forum where one person sayed that when he deleted an object with the delete operator, it appeared not to be any memory amount decrease in the Windows Task manager.
Also, this person was told that the Windows Task manager is not very reliable in this way.
So my question is: when I delete (with delete operator) a sprite in my game I don't see in Task manager that memory amount is decreasing, but the game continues creating sprites, the memory amount increases. Do I have to consider this as a memory leak or should I just ignore Windows Task manager?
Also I have a related question. I delete my sprite with this line:
delete mySprite; // being mySprite a pointer to a MySprite class object
MySprite is a class that I developed myself, but I left the destructor in it empty (as it came by default). Is this okay or should I manually deallocate class members in the destructor's body?
Hope I made it clear. Thanks in advance for your help!
Bye, bye! ;)
You should manually deallocate class members.
Don't pay too much attention to the task manager.
If you deleted the sprite and everything went ok you can assume
the memory was freed.
HTH.
Don't pay too much attention to the task manager.
If you deleted the sprite and everything went ok you can assume
the memory was freed.
HTH.
Quote:Original post by PezMutanTIgnore task manager. Task manager shows your application's working set size, which is the amount of memory the OS has set aside for your application. The way the CRT memory allocation functions work is they request blocks of memory from the OS (Which are something like 64KB I think) when they need it, and free them when it's done. However, for performance reasons, the CRT is likely to keep a certain number of these blocks allocated and not free them as soon as it can. Further, the OS doesn't have to actually free the blocks when the CRT asks it to; it might keep them allocated for performance reasons as well.
Hi everyone!
I've been reading an old post from this forum where one person sayed that when he deleted an object with the delete operator, it appeared not to be any memory amount decrease in the Windows Task manager.
Also, this person was told that the Windows Task manager is not very reliable in this way.
So my question is: when I delete (with delete operator) a sprite in my game I don't see in Task manager that memory amount is decreasing, but the game continues creating sprites, the memory amount increases. Do I have to consider this as a memory leak or should I just ignore Windows Task manager?
Quote:Original post by PezMutanTThat's perfectly fine. After your destructor is called (Even if it's empty), the compiler will call the destructor of all class member variables manually. You should only ever explicitly call the destructor of a class (Member variable or otherwise) if you're writing a memory manager and are using placement new.
Also I have a related question. I delete my sprite with this line:
delete mySprite; // being mySprite a pointer to a MySprite class object
MySprite is a class that I developed myself, but I left the destructor in it empty (as it came by default). Is this okay or should I manually deallocate class members in the destructor's body?
However, if any of the member variables are created with new, you need to delete them from the destructor.
Thanks a lot to both of you for replying!
That's what I understood, you don't call explicitly the destructor except when you are using placement new. But if I want to delete a sprite from memory, am I doing well "deleting" it, right?
In conclusion, my destructor should only have "delete's" for those members that I created earlier with a new operator? The rest of members should deallocate automatically even if the destructor is empty, right?
The sprite I am trying to delete is of a class named Fire. This class is derived from a class named Sprite. Fire class has no own member variables, but Sprite class is like this:
The Fire class constructor is this:
As I am not initializing any member variable with new operator, I would say I can keep my destructor empty. Is this correct?
Thanks a lot, people!
Quote:Original post by Evil Steve
That's perfectly fine. After your destructor is called (Even if it's empty), the compiler will call the destructor of all class member variables manually. You should only ever explicitly call the destructor of a class (Member variable or otherwise) if you're writing a memory manager and are using placement new.
However, if any of the member variables are created with new, you need to delete them from the destructor.
That's what I understood, you don't call explicitly the destructor except when you are using placement new. But if I want to delete a sprite from memory, am I doing well "deleting" it, right?
In conclusion, my destructor should only have "delete's" for those members that I created earlier with a new operator? The rest of members should deallocate automatically even if the destructor is empty, right?
The sprite I am trying to delete is of a class named Fire. This class is derived from a class named Sprite. Fire class has no own member variables, but Sprite class is like this:
class Sprite{protected: LPDIRECT3DDEVICE9 m_Device; LPD3DXSPRITE m_pSprite; LPDIRECT3DTEXTURE9 m_pTextura; D3DCOLOR m_AlphaColor; RECT m_Rect; D3DXVECTOR3 m_v3Center; D3DXVECTOR3 m_v3Position; int m_Anchura; int m_Altura; int m_VelocidadX; int m_VelocidadY; BOOL m_bDestruir;...
The Fire class constructor is this:
Fire::Fire(LPDIRECT3DDEVICE9 device, LPCTSTR archivo, int rLeft, int rTop, int rRight, int rBottom, int x, int y){ m_bDestruir = FALSE; m_Device = device; m_Rect.left = rLeft; m_Rect.top = rTop; m_Rect.right = rRight; m_Rect.bottom = rBottom; m_Anchura = m_Rect.right - m_Rect.left; m_Altura = m_Rect.bottom - m_Rect.top; m_v3Center = D3DXVECTOR3(0, 0, 0); m_v3Position = D3DXVECTOR3(FLOAT(x), FLOAT(y), 0); m_AlphaColor = D3DCOLOR_ARGB(255, 255, 255, 255); m_VelocidadX = m_VelocidadY = 0; D3DXCreateSprite(device, &m_pSprite); D3DXCreateTextureFromFileEx(m_Device, archivo, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, m_AlphaColor, NULL, NULL, &m_pTextura);}
As I am not initializing any member variable with new operator, I would say I can keep my destructor empty. Is this correct?
Thanks a lot, people!
You are not but D3DXCreateSprite and D3DXCreateTextureFromFileEx probably
do, you need to free them using the appropriate d3dx functions.
do, you need to free them using the appropriate d3dx functions.
Quote:Original post by PezMutanTCorrect. The destructor is automatically called for all your member variables. If you have any pointers as member variables, the destructor for a pointer does nothing (Since you might have a pointer to an object that's still in use; e.g. a parent sprite or something). If that pointer is allocated with new, you need to delete it. If it's a C FILE handle, you need to fclose() it. Etc, etc.
That's what I understood, you don't call explicitly the destructor except when you are using placement new. But if I want to delete a sprite from memory, am I doing well "deleting" it, right?
In conclusion, my destructor should only have "delete's" for those members that I created earlier with a new operator? The rest of members should deallocate automatically even if the destructor is empty, right?
Quote:Original post by PezMutanTYou still need to free your sprite and texture, because they're pointers (Unless you're still using them after the object has been destroyed - e.g. if you pass the texture to some sort of resource manager for caching).
The sprite I am trying to delete is of a class named Fire. This class is derived from a class named Sprite. Fire class has no own member variables, but Sprite class is like this:
*** Source Snippet Removed ***
The Fire class constructor is this:
*** Source Snippet Removed ***
As I am not initializing any member variable with new operator, I would say I can keep my destructor empty. Is this correct?
So your Sprite destructor (Since that's what has the members, not the Fire class, so it makes most sense to do it there) should probably be:
Sprite::~Sprite(){ if(m_pSprite) m_pSprite->Release(); if(m_pTextura) m_pTextura->Release();}
Also, a little off topic; it might be an idea to call AddRef() on the device pointer when you construct the sprite, and Release() it in the destructor. That keeps everything nice, since if you end up releasing your device and then use your sprite, it won't crash because your sprite has incremented the reference count.
Also off topic, it's generally better to use one ID3DXSprite class in your entire app. The ID3DXSprite class has a vertex and index buffer internally, so creating multiple ID3DXSprite's means multiple VBs and IBs, which is bad for memory usage and also bad for speed (Since you need to swap between them when rendering).
Ok, thank both of you very much! You made things clearer to me.
But those off-topic comments from Evil Steve about ID3DXSprite made me think... So it's supposed to use only one ID3DXSprite pointer in the whole application? If so, can I manage several sprites with it? Is it done with the AddRef() and Release() functions that you were saying?
This is my first contact with DirectX, I was using it just to know how it works, but I see I didn't get it very well... :)
Thanks a lot!!
Bye, bye! ;)
But those off-topic comments from Evil Steve about ID3DXSprite made me think... So it's supposed to use only one ID3DXSprite pointer in the whole application? If so, can I manage several sprites with it? Is it done with the AddRef() and Release() functions that you were saying?
This is my first contact with DirectX, I was using it just to know how it works, but I see I didn't get it very well... :)
Thanks a lot!!
Bye, bye! ;)
Quote:Original post by PezMutanTThere's nothing too bad about using one ID3DXSprite per sprite, it's just better if you didn't.
But those off-topic comments from Evil Steve about ID3DXSprite made me think... So it's supposed to use only one ID3DXSprite pointer in the whole application? If so, can I manage several sprites with it? Is it done with the AddRef() and Release() functions that you were saying?
This is my first contact with DirectX, I was using it just to know how it works, but I see I didn't get it very well... :))
I'd handle this by creating the ID3DXSprite after you create your device, and passing it to the constructor of Fire in the same way that you pass your device pointer in. And yeah, I'd AddRef() it in the constructor and Release() it in the destructor just to keep things clean.
Also, if you're not already, you should be using the Debug Runtimes, since they'll help track down bugs and show up memory leaks from not Release()ing D3D objects.
That would mean your code would look like:
class Sprite{ Sprite(LPDIRECT3DDEVICE9 pDevice, LPD3DXSPRITE pSprite) : m_Device(pDevice), m_pSprite(pSprite), m_pTexture(NULL), m_AlphaColor(D3DCOLOR_ARGB(255, 255, 255, 255)), m_v3Center(0, 0, 0), m_v3Position(0, 0, 0), m_Anchura(0), m_Altura(0), m_VelocidadX(0), m_VelocidadY(0), m_bDestruir(FALSE) { m_Rect.top = 0; m_Rect.bottom = 0; m_Rect.left = 0; m_Rect.right = 0; m_Device->AddRef(); m_pSprite->AddRef(); } virtual ~Sprite() { if(m_pSprite) m_pSprite->Release(); if(m_pTextura) m_pTextura->Release(); }protected: LPDIRECT3DDEVICE9 m_Device; LPD3DXSPRITE m_pSprite; LPDIRECT3DTEXTURE9 m_pTextura; D3DCOLOR m_AlphaColor; RECT m_Rect; D3DXVECTOR3 m_v3Center; D3DXVECTOR3 m_v3Position; int m_Anchura; int m_Altura; int m_VelocidadX; int m_VelocidadY; BOOL m_bDestruir;};Fire::Fire(LPDIRECT3DDEVICE9 device, LPD3DXSPRITE sprite, LPCTSTR archivo, int rLeft, int rTop, int rRight, int rBottom, int x, int y) : Sprite(device, sprite){ m_Rect.left = rLeft; m_Rect.top = rTop; m_Rect.right = rRight; m_Rect.bottom = rBottom; m_Anchura = m_Rect.right - m_Rect.left; m_Altura = m_Rect.bottom - m_Rect.top; m_v3Position = D3DXVECTOR3(FLOAT(x), FLOAT(y), 0); D3DXCreateTextureFromFileEx(m_Device, archivo, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, m_AlphaColor, NULL, NULL, &m_pTextura);}
EDIT: It would probably be cleaner to pass the RECT and width, height and position parameters to the Sprite() constructor, since they'll need set for every sprite anyway. They'd just be passed in like how the device and sprite pointer are passed in. But that's really just a style thing [smile]
Wow, I really appreciate your work with my code, Evil Steve :)
I'm sorry but I still don't understand two things: (by the way, I am sorry because I know this discussion shouldn't be in this forum)
- Reading the ID3DXSprite reference, it mention something about a list of batched sprites, like here:
"ID3DXSprite::Draw Adds a sprite to the list of batched sprites."
I don't understand how I should manage that list and if I could access every element of it (because every element would be a different sprite). Is it related with the AddRef() and Release() functions?
- Why a virtual destructor? If I only have one destructor in the parent class, shouldn't it be enough?
I'm sorry, but I got a little confuse after your last reply.
Thank you very much!
I'm sorry but I still don't understand two things: (by the way, I am sorry because I know this discussion shouldn't be in this forum)
- Reading the ID3DXSprite reference, it mention something about a list of batched sprites, like here:
"ID3DXSprite::Draw Adds a sprite to the list of batched sprites."
I don't understand how I should manage that list and if I could access every element of it (because every element would be a different sprite). Is it related with the AddRef() and Release() functions?
- Why a virtual destructor? If I only have one destructor in the parent class, shouldn't it be enough?
I'm sorry, but I got a little confuse after your last reply.
Thank you very much!
Quote:Original post by PezMutanT
- Why a virtual destructor? If I only have one destructor in the parent class, shouldn't it be enough?
Whenever you call a non-virtual member function through a pointer or reference to the base class, the base class version of the function is called, not the derived one. The destructor is a member function; therefore, whenever you call 'delete' on a pointer to the base class, and the destructor of the base class is not virtual, the base class version is called. That's bad, because if the pointer actually points to a derived instance (and the ability to do that is what motivated you in the first place), then the program will try to clean up a derived instance as if it were a base instance. Note: this does not simply clean up the base part of the class and leave the derived part alone. It is explicitly undefined behaviour.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement