Jump to content
  • Advertisement
Sign in to follow this  
aeroz

Deleting an Object that is being used

This topic is 3704 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

I have a general C plus plus question: What does happen when you are inside an object's method and the the object is deleted? Example: (corrected)
class Abc;

class Obj
{
public:
   void DoSomething()
   {
      Abc->DeleteObj();
      /* What now? */
   }
   Abc* blaBla;
};

class Abc
{
public:
   Obj* obj;
   void DeleteObj() { delete obj; }
};

int main()
{
   Obj obj1;
   Abc abc;

   abc.obj = &obj1;
   obj1.blaBla = &abc;
   obj1.DoSomething();
}

I know it's not a good example since both classes have pointers to each other. But what would happen with the "obj1" object? Would the destructor be called? Would the DoSomething() function continue executing? Thank you for the help! [Edited by - aeroz on June 21, 2008 4:16:29 PM]

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by aeroz
I know it's not a good example since both classes have pointers to each other.

Well, one has, but I'll assume the other is a typo and should be a pointer too ;) In main() you should also have &obj1 to assign to the pointer.

Quote:
Original post by aeroz
But what would happen with the "obj1" object? Would the destructor be called?

Yes, an implicit one, because you have none defined. Worse though, it's memory is freed after destruction which is a Bad Thing because it was allocated on the stack of main().

Quote:
Original post by aerozWould the DoSomething() function continue executing?

In this case, no, because of the stack issue. However, in the following, proper example it would continue just fine:


class Abc;

class Obj
{
public:
Abc* blaBla;
void DoSomething()
{
blaBla->DeleteObj();
}
};

class Abc
{
public:
Obj* obj;
void DeleteObj() { delete obj; }
};

int main()
{
Obj* obj1 = new Obj;
Abc abc;

abc.obj = obj1;
obj1->blaBla = &abc;
obj1->DoSomething();
}



I'm not sure if the standard guarantees this behavior to be well defined, but practically it'll work fine.
AFAIK, you only get undefined behavior if you try to use members variables or (virtual) functions of the deleted object in DoSomething() after calling DeleteObj().

Share this post


Link to post
Share on other sites
This is just bad design. It would be the same as trying to delete the 'this' keyword:



void someClass::someFunciton()
{
delete this;

// What happens now??? What is 'this'?? What am I acting on?
}




Firstly, after that delete command, you will be acting upon memory that has been deleted, essentially causing a "buffer overflow" or worse, a heap corruption. If you can, try to rework your logic.

Share this post


Link to post
Share on other sites
Quote:
Original post by RealMarkP
This is just bad design. It would be the same as trying to delete the 'this' keyword:

There's nothing wrong with delete this; I use it in reference counted objects:

void Object::Release() {
if (--m_nReferences == 0) {
delete this;
}
}


Combine this with private destructors, and you enforce referencing counting.

Share this post


Link to post
Share on other sites
Obj contains an Abc object but Abc contains a pointer to an Obj object. So, it's basically a chain of objects. If one instance of Abc deletes its Obj pointer, it simply breaks the chain (probably causing a memory leak). You're not actually deleting an object "in use".

If you're finding yourself stuck in a circular dependency such as this, you probably need to seriously rethink your code. As for deleting object while in use, you may want to consider delete "events" instead. This allows other parts of the app to communicate that it wishes to delete while the actual deletion is held off until the object is not in use.

Hope this helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike nl
Quote:
Original post by RealMarkP
This is just bad design. It would be the same as trying to delete the 'this' keyword:

There's nothing wrong with delete this; I use it in reference counted objects


Almost, but I think you get the idea.

@OP, could you post your actual interface. It would be easier to make suggestions if we knew the task at hand.

Share this post


Link to post
Share on other sites
Thank you for your answers!

Quote:
Well, one has, but I'll assume the other is a typo and should be a pointer too ;) In main() you should also have &obj1 to assign to the pointer.
Yes, my mistake! (I've corrected it now.)
Quote:
AFAIK, you only get undefined behavior if you try to use members variables or (virtual) functions of the deleted object in DoSomething() after calling DeleteObj().
That's exactly what I think, but I don't know if it's true. (platform/compiler dependent?)
Quote:
Yes, an implicit one, because you have none defined. Worse though, it's memory is freed after destruction which is a Bad Thing because it was allocated on the stack of main().

Quote:
Original post by aerozWould the DoSomething() function continue executing?


In this case, no, because of the stack issue. However, in the following, proper example it would continue just fine:
Mike nl: Yes, I agree. I also have dynamically allocated objects. But is it really true that in your example the DoSomething() method would continue running?

Actually I came across this problem while reading this article: Game States
In the Intro state itself the state is being changed (that means that the Intro state is being deleted). Here the code:
void CIntroState::HandleEvents(CGameEngine* game)
{
/* .... code 1 */

if ( /* key to change state is pressed */ )
game->ChangeState( CPlayState::Instance() );

/* .... code 2 */
}
In ChangeState() the current state (Intro) is deleted and a new one is initialized (CPlayState). Will code 2 be executed?

Share this post


Link to post
Share on other sites
@fpsgamer

Question regarding your link: (item #4)

Quote:
You must be absolutely 100% positive sure that no one even touches the this pointer itself after the delete this line. In other words, you must not examine it, compare it with another pointer, compare it with NULL, print it, cast it, do anything with it.


I don't understand why it would be wrong to do something with "this" it self afeter "delete this" as long as such operation doesn't involve dereferencing "this"


printf("%x", this)
if (this > 0x80000000)
int* p = (int*) this;

and so on. Can delete have side effects on the pointer itself?

Share this post


Link to post
Share on other sites
Quote:
Original post by janta
@fpsgamer

Question regarding your link: (item #4)

Quote:
You must be absolutely 100% positive sure that no one even touches the this pointer itself after the delete this line. In other words, you must not examine it, compare it with another pointer, compare it with NULL, print it, cast it, do anything with it.


I don't understand why it would be wrong to do something with "this" it self afeter "delete this" as long as such operation doesn't involve dereferencing "this"


printf("%x", this)
if (this > 0x80000000)
int* p = (int*) this;

and so on. Can delete have side effects on the pointer itself?


Well you just deleted this, what obligation does the compiler have to keep the this pointer around?

It would be no more valid than doing this:


class Foo
{
int* myIntPtr;
public:
...
void freeFoo()
{
delete this;
/* I'm not dereferencing these pointers,
but the following is still bad:
*/

assert(myIntPtr != 0);
assert(this != 0);
}
};










Once you delete the object, everything having to do with this is kaput, including the this pointer.

Share this post


Link to post
Share on other sites
Actually, that really means:

delete this;
assert(this->myIntPtr != 0);
assert(this != 0);

So in the first assert, you are dereferencing a deleted pointer, so I don't think that argument holds. However, I'm not sure what does happen to this, so yes, I'd also recommend against doing anything with it.

Practically, I think nothing happens with the pointer itself, just like any other pointer that you delete. However, because you can't dereference it, it's kind of useless after the delete.

Then again, C++ has weird stuff going on with pointers and multiple inheritance and virtual stuff, so I can't completely rule out nothing funky will happen. Just don't use a pointer after deleting it, is generally sound advice ;)

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!