• Advertisement
Sign in to follow this  

C++ Struct Destructor Question

This topic is 3739 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is memory allocated for struct on the heap? If I have DirectX interfaces needed to release, can I do it in the destructor of a structure? I have some wierd problems with a struct destructor like this: struct EnemyShip { IDirect3DTexture9* tex; EnemyShip(); ~EnemyShip(); }; EnemyShip::EnemyShip() { HR(D3DXCreateTextureFromFile(gd3dDevice, TEXT("alienship.bmp"), &(tex))); } EnemyShip::~EnemyShip() { ReleaseCOM(this->tex); }

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by ynkm169
Is memory allocated for struct on the heap?


Depends on the instance. Did you create it with new?

Share this post


Link to post
Share on other sites
Quote:
Original post by Driv3MeFar
Quote:
Original post by ynkm169
Is memory allocated for struct on the heap?


Depends on the instance. Did you create it with new?


I use the following line to initialize IDirect3DTexture9* tex, so I did not use NEW. However I think I am supposed to release it with releaseCOM(); I put it in the structure destructor and my program says access violation.


HR(D3DXCreateTextureFromFile(gd3dDevice, TEXT("alienship.bmp"), &(tex)));

Share this post


Link to post
Share on other sites
whatsup with this releaseCOM thing?

where did you see that as an example?

isn't there a direct3d9texture->release() or something like that?

Share this post


Link to post
Share on other sites
Quote:
Original post by Maverick_24
whatsup with this releaseCOM thing?

where did you see that as an example?

isn't there a direct3d9texture->release() or something like that?


sorry. It is defined as this:

#define ReleaseCOM(x) { if(x){ x->Release();x = 0; } }

Share this post


Link to post
Share on other sites
I just found the problem. I have the following function to initialize my list of structures. It turns out that even if I pushed the structure down the std::list, the destructor is still called for it at the end of the function. Therefore, later on, when I say something like this:

std::list<EnemyShip>::iterator i = mEnemyShipList.begin();
HR(mSprite->Draw(i->tex, 0, &mShipCenter, 0, D3DCOLOR_XRGB(255, 255, 255)));

ERROR is produced when I use "i->tex" that has already been released.


void SpriteDemo::enemyShipList()
{
EnemyShip enemyShip1;
enemyShip1.pos = D3DXVECTOR3(-300.0f, -300.0f, 0.0f);
enemyShip1.realPos = D3DXVECTOR3(-300.0f, -300.0f, 0.0f);
enemyShip1.bulletColorNormal = D3DCOLOR_XRGB(255, 255, 255);
mEnemyShipList.push_back(enemyShip1);

EnemyShip enemyShip2;
enemyShip2.pos = D3DXVECTOR3(300.0f, -300.0f, 0.0f);
enemyShip2.realPos = D3DXVECTOR3(300.0f, -300.0f, 0.0f);
enemyShip2.bulletColorNormal = D3DCOLOR_XRGB(255, 0, 255);
mEnemyShipList.push_back(enemyShip2);

EnemyShip enemyShip3;
enemyShip3.pos = D3DXVECTOR3(300.0f, 300.0f, 0.0f);
enemyShip3.realPos = D3DXVECTOR3(300.0f, 300.0f, 0.0f);
enemyShip3.bulletColorNormal = D3DCOLOR_XRGB(255, 255, 0);
mEnemyShipList.push_back(enemyShip3);

EnemyShip enemyShip4;
enemyShip4.pos = D3DXVECTOR3(-300.0f, 300.0f, 0.0f);
enemyShip4.realPos = D3DXVECTOR3(-300.0f, 300.0f, 0.0f);
enemyShip4.bulletColorNormal = D3DCOLOR_XRGB(0, 255, 255);
mEnemyShipList.push_back(enemyShip4);
}

Share this post


Link to post
Share on other sites
When you add an object to a list, you create a copy. Naturally you now have two objects. Each will have its destructor called in due course. For the enemyShip1/2/3/4 objects, "due course" is at the end of scope for the enemyShipList() member function.

At this point, ReleaseCOM is called. But the copy of each object sitting in the list contain tex pointers that point to the objects you just released. Obviously this is bad, because these objects will now operate on "dangling" pointers. I think you understand this, already, but it's worth being crystal clear.

So, things to lookup/read in order to fix this:

1. The rule of three
2. How to make an object un-copyable by declaring private copy constructor and assignment operators (or how to use boost::noncopyable)
3. reference-counted smart pointers (e.g. boost::shared_ptr)

2 and 3 are often used in combination.

Share this post


Link to post
Share on other sites
COM provides a smart-pointer IIRC which is useful for this sort of thing.

Also, it is not useful to set a pointer to 0 in a destructor, and anyway, a macro like that can be done as a function with no real disadvantages and the very definite advantage of having an actual function instead of a text substitution hack. Such "release" macros (including the classic version using 'delete' instead of an API Release() call) are a dangerous relic of a forgotten era.

Also, use constructors to simplify your code.


EnemyShip enemyShip1;
enemyShip1.pos = D3DXVECTOR3(-300.0f, -300.0f, 0.0f);
enemyShip1.realPos = D3DXVECTOR3(-300.0f, -300.0f, 0.0f);
enemyShip1.bulletColorNormal = D3DCOLOR_XRGB(255, 255, 255);
mEnemyShipList.push_back(enemyShip1);


Notice how you can just write 'D3DXVECTOR3(-300.0f, -300.0f, 0.0f)' instead of making a separate D3DXVECTOR3 variable, assigning to its members, and then proceeding with that? You should set up your code to offer similar functionality:


EnemyShip::EnemyShip(D3DXVECTOR3 position, D3DCOLOR_XRGB bulletColor) :
pos(position), realPos(position), bulletColorNormal(bulletColor) {
// as before
}

mEnemyShipList.push_back(EnemyShip(D3DXVECTOR3(-300.0f, -300.0f, 0.0f),
D3DCOLOR_XRGB(255, 255, 255));

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement