Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

in C++ which happens first, the copy of a return object or local object's destructors? [duplicate]

Tags:

I imagine there's an answer to this somewhere, but I couldn't find it because there are lots of threading questions, and mine's pretty simple by comparison.

I'm not trying to make a threadsafe copy or assignment constructor or anything like that.

What I'm wondering, is if I have a class that represents a mutex lock and I return from a function that instantiates it, which happens first, the destructor of my mutex (thus unlocking it) or the copy constructor of the return value. Here's my example:

string blah::get_data(void)
  {
    MutexLock ml(shared_somewhere_else); // so this locks two threads from calling get_data at the same time

    string x = "return data";
    return x;
  }

Somewhere else, we call get_data...

 string result = get_data();

Thinking back to C for a second, you never return a pointer to a global variable, because the local variable goes out of scope after you return.

C++ doesn't have this problem because x will get copied into result. What I'm wondering is when that happens. Will my lock free before the copy is made?

In this simple example "return data" is static information, but what I'm working with, it's data that can be changed by another thread (also locked on the same MutexLock) so if the lock frees before the copy-to-result is made, the copy could get corrupted.

I'm not sure I'm explaining the question well, so I'll try to clarify if this doesn't make sense.

like image 454
stu Avatar asked Oct 15 '15 13:10

stu


People also ask

What is destructor What's the order in which the local objects are destructed?

What's the order that local objects are destructed? ¶ Δ In reverse order of construction: First constructed, last destructed.

Is destructor called after return?

However, in your current implementation you're actually returning a shallow copy of NodeContainer. Once your copy goes out of scope its destructor is called, which deallocates its memory, which in this case is the original memory of your member, effectively making your member invalid.

Why is the destructor in reverse order?

Objects are always destroyed in reverse order of their creation. The reason for reverse order is, an object created later may use the previously created object.

Do destructors have a return value?

A destructor takes no arguments and has no return type.


2 Answers

For previous standards (here I will use C++ 03), the closest the standard comes to declaring the sequence of operations in a return is from 6.6

6.6 Jump statements

  1. On exit from a scope (however accomplished), destructors (12.4) are called for all constructed objects with automatic storage duration (3.7.2) (named objects or temporaries) that are declared in that scope, in the reverse order of their declaration. Transfer out of a loop, out of a block, or back past an initialized variable with automatic storage duration involves the destruction of variables with automatic storage duration that are in scope at the point transferred from...

The return statement must complete in order to exit the [function] scope, implying that the copy-initialization must also complete. This order is not explicit. Various other quotes from 3.7.2 and 12.8 concisely state the same as above without providing explicit order. Working revisions (after Nov. 2014) include the quote below to address that. The defect report clarifies the change.

From the current working draft (N4527) of the standard as seen on the date of this question

6.6.3 The Return Statement

  1. The copy-initialization of the returned entity is sequenced before the destruction of temporaries at the end of the full-expression established by the operand of the return statement, which, in turn, is sequenced before the destruction of local variables (6.6) of the block enclosing the return statement.

Notice that this quote refers directly to 6.6. So I think it is safe to assume that the Mutex object will always be destroyed after the return expression has copy-initialized the return value.

like image 72
Rollen Avatar answered Nov 15 '22 12:11

Rollen


While I am no standard guru, it seems quite obvious that destructors should be called after the copy is made - otherwise the very object you are copying would be destroyed before it is copied... :)

like image 34
SergeyA Avatar answered Nov 15 '22 12:11

SergeyA