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,
q
is destroyed. But the memory to whichq
points is not freed sinceq
is a builtin pointer and not a shared_ptr. And unless we explicitly write deleteq
the 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 thatp
still point to the same memory which has been freed. Sop
is now a dangling pointer and usingp
in the statementint foo=*p
is 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
q
instead of creating a new temporary usingq
as 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 namedq
is created which is a smart pointer instead of a built in pointer from the outer scope.This local variable
q
has nothing to do with bothp
orq
from the outer scope and hence when this localq
goes out of scope shared_ptr's destructor is called. But note the memory to which the outerp
orq
points 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 namedq
instead of a temporary usingq
as parameter.In the above code if we try to access local
q
's value using*q
then we will get undefined behavior(which may crash the program/segmentation fault) since we are dereferencing a null pointer. If we remove this*q
then 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.