Hi i am reading C++ primer 5th edition and i think i have spotted one error under the section shared_ptr. First i am writing the code and the explanation that they have given. Then i will write what i think is the error and what i think is actually happening. The code is as follows:
shared_ptr<int> p(new int(42));// reference count is 1
int *q = p.get();// ok: but don't use q in any way that might delete its pointer
{//new block started
shared_ptr<int>(q);
}// block ends, q is destroyed, and the memory to which q points is freed
int foo = *p;// undefined; the memory to which p points was freed
The explanation they have given is as follows:
In this case, both p and q point to the same memory. Because they were created independently from each other, each has a reference count of 1. When the block in which q was defined ends, q is destroyed. Destroying q frees the memory to which q points. That makes p into a dangling pointer, meaning that what happens when we attempt to use p is undefined. Moreover, when p is destroyed, the pointer to that memory will be deleted a second time.
Now i think the error is the statement "When the block in which q was defined ends, q is destroyed.Destroying q frees the memory to which q points." and also the reasoning they gave behind why p is a dangling pointer is faulty. Below is my reasoning why p is a dangling pointer and why first quoted statement is an error.
- When the block in which q was defined ends,
qis destroyed. But the memory to whichqpoints is not freed sinceqis a builtin pointer and not a shared_ptr. And unless we explicitly write deleteqthe corresponding memory will not be freed. - Now, inside the new block we have created a temporary shared_ptr using q. But this temporary is independent of
p. and so when this inner block ends the temporary is destroyed and hence the memory is freed. But note thatpstill point to the same memory which has been freed. Sopis now a dangling pointer and usingpin the statementint foo=*pis undefined.
I think this is the correct explanation of why p is a dangling pointer and also the correction that should be there. Can someone confirm if this is right or am i doing something wrong?
C++ Primer 5th edition as well as your explanation has made one common mistake while trying to explain this program. Note that the statement:
creates a new temporary named
qinstead of creating a new temporary usingqas parameter to ashared_ptr's constructor. The below example code shows this:The 2nd point of your explanation is correct only if we use
shared_ptr<int>{q};instead ofshared_ptr<int>(q);.This means:
Since the author has used
shared_ptr<int>(q);a local variable namedqis created which is a smart pointer instead of a built in pointer from the outer scope.This local variable
qhas nothing to do with bothporqfrom the outer scope and hence when this localqgoes out of scope shared_ptr's destructor is called. But note the memory to which the outerporqpoints is not freed.So afterwards when we write
int foo = *p;there is no undefined bahavior.Below is the code that shows that
shared_ptr<int>(q);defines a local namedqinstead of a temporary usingqas parameter.In the above code if we try to access local
q's value using*qthen we will get undefined behavior(which may crash the program/segmentation fault) since we are dereferencing a null pointer. If we remove this*qthen the program have no undefined behavior.Now even in the next edition of the book(6th edition) the author is using
auto local = shared_ptr<int>(q);when he could have just usedshared_ptr<int>{q};to make his point.