6

I have pointer object to singleton class.

Thread 1: Currently executing a member function of the above said object.
Thread 2: Deletes the above object when the object's member function is still being executed by Thread 1.

What happens to Thread 1 where the member function is being executed? Whether the execution will be stopped midway?

Unihedron
11.1k13 gold badges65 silver badges72 bronze badges
asked Aug 9, 2013 at 13:55
4
  • 6
    A good place to use the term 'undefined behaviour'. Commented Aug 9, 2013 at 13:57
  • 2
    Undefined behaviour. One solution: don't use a singleton. Use an object that is sure to outlive both threads. Commented Aug 9, 2013 at 13:57
  • @juanchopanza the weird thing here is that we have a singleton and it isn't outliving both threads. (That said, yeah, drop the sillyton) Commented Aug 9, 2013 at 14:05
  • @juanchopanza A singleton is guaranteed to outlive all threads. If the object is being deleted in a thread, it isn't a singleton. Commented Aug 9, 2013 at 14:29

4 Answers 4

4

It is probably undefined behavior, unless you are extra careful.

Deleting the object while your thread accesses it in an unordered (non-synchronized, basically) manner is undefined behavior, even if you get lucky.

Accessing the members of the object (not just running a member: actually accessing a member -- calling a member function, reading a member variable, etc) after you have synchronized with the delete from the main thread is also undefined behavior.

If you carefully synchronize with the main thread, then do not access the member data nor call a different member function after that synchronization, and the main thread deletes the object after that synchronization, then you are perfectly ok.

Almost anything short of that results in undefined behavior.

While undefined behavior can do almost anything, it would be unexpected undefined behavior for this to cause the execution of the code in the member function to suddenly stop just because the object is deleted. More likely you'd get segfaults, memory corruption, or the like. What is worse is that in many cases, things would work "just fine".

answered Aug 9, 2013 at 15:08
Sign up to request clarification or add additional context in comments.

Comments

2

You will most likely get undefined behavior. Thread 1 can get a seg fault or it may continue merrily on its way if it accesses no member data (and makes no virtual function calls) after the object's deletion. It also depends on what happens to the memory area after deletion. Is it cleared? Is it non-writable/non-readable? It's all highly implementation dependent as well dependent on the data needs of your application in terms of reusing the data area to handle other allocations.

The guidance is to never delete an object until all use of it is complete. There are some exceptions where member functions delete the object they operate on ensuring there is no more member access after the point of deletion. But other than those few cases that actually justify deletion in a member, don't do this.

In the multi-threaded environment you are describing, be absolutely certain to coordinate object lifetime with object use or you may get very difficult to debug (platform dependent and non-deterministic) behavior.

answered Aug 9, 2013 at 13:57

1 Comment

+1 Though I would say it's undefined behavior iff member data is accessed after the delete. It's easy to imagine this as a pure race condition, but it might not be. For all we know, there is synchronization between thread1's advancement through the function and thread2's deletion, in which case this behavior is well-defined.
0

Undefined behavior is the right answer. To avoid such things consider using smart pointers, like this: http://www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm or this: http://en.cppreference.com/w/cpp/memory/shared_ptr. They have reference counting mechanism that doesn't allow you to delete using object.

answered Aug 9, 2013 at 14:11

2 Comments

Would smart pointers ensure when the pointer itself is accessed from different threads? For example , in thread 1 a method is called as uniqueptr->func , while the execution continues, in another thread uniqueptr->reset() is called. Would calling reset on smart pointer wait until func executes?
No, you should provide a mechanism for multithread usage on your own and 'wait util func executes' on your own;). More info about smart ptrs and multiple threads see here: stackoverflow.com/questions/14482830/…
0

Short answer: You shouldn't do this... You need to make sure the object is not being used before deleting it.

In terms of what the C++ standard specifies, it's (probably) undefined behaviour - something unexpected may well happen. The basis for this is that it's undefined behaviour to use any member (function or variable) of an object after the object has been destroyed. Of course, if the member function looks like this:

void foo::func()
{
 for(;;)
 {
 // do nothing here 
 }
}

then it's NOT undefined behaviour, and the thread can be left running indefinitely, without any ill effect, and the behvaiour (I believe) is well defined (it just keeps running).

Certainly thread 1's execution will definitely not stop simply because the object is being deleted. That is, unless the object actually contains a thread object for thread 1 - in which case, the destructor of the thread object may kill the thread.

In practice, if the object is deleted, it's memory is freed, and the memory may well be reused for some other object a small amount of time later. Depending on what the member function is doing, e.g, what parts of the object it's referring to, and how it's using those members, it may cause a crash, or if it does something like x++; (where x is a member variable), it will modify some memory it no longer is the owner of - and that can be quite tricky to debug, because it will appear like something is randomly changing other objects... This is definitely NOT good (and most likely, it will only happen SOMETIMES, making it really hard to spot when it goes wrong).

Nothing good can possibly come out of this.

You MUST make sure the object is not in use in any way to delete it. One way to do that is of course to have the thread object for thread 1, and kill the thread.

answered Aug 9, 2013 at 14:08

8 Comments

I'm pretty sure that struct foo { void SelfDestroy() { delete this; std::cout << "I was deleted!\n"; } }; int main() { foo* f = new foo; f->SelfDestroy(); } is not undefined behavior, but it has this being deleted while a member function is being executed.
@Yakk But delete this isn't the question. The question involved deleting an object in one thread while it is still being used in another.
Ok, will try to reformulate my answer to cover the case where an object is being destroyed by another thread, where the original thread is running in a loop inside a member function, without mentioning destruction of the object.
@Yakk: I think I've clarified what is undefined behaviour, and that deleting the object itself doesn't result in undefined behaviour - it is the use of any member after the object has been deleted that is UB.
It is actually any unordered (relative to the delete) access to member data that is deleted, or any ordered and after access to member data, that causes undefined behavior: if you don't have a point of synchronization in the member that coordinates with the deletion of the object, and then doesn't access any member data after that point, you have UB even if you get lucky because the member happened to be at a late enough point of execution.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.