 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
hzhuo1@gmail.com Guest
|
Posted: Tue Sep 19, 2006 12:14 am Post subject: Why doesn't shared_ptr generate a cycle? |
|
|
Consider the following code using boost::shared_ptr:
#include<iostream>
#include<boost/shared_ptr.hpp>
#include<boost/weak_ptr.hpp>
using namespace std;
class B;
class A{
private:
boost::shared_ptr<B> x;
public:
A();
void create(B* bb);
};
class B{
private:
boost::shared_ptr<A> y;
public:
B(A* aa){
y=boost::shared_ptr<A>(aa);
}
};
A::A(){ }
void A::create(B* bb){
x=boost::shared_ptr<B>(bb);
}
int main(){
A *a= new A;
B *b= new B(a);
a->create(b);
return 1;
}
In the main function , we create two dynamic objects *a and *b. *a
contains a shared_ptr<B> which points to *b, whereas *b contains a
shared_ptr<A> which points to *a. Before the main function returns ,it
should call A and B's destruction functions. But since A contains a
shared_ptr<B>,calling to A's destruction function will cause a call to
B's destruction function. Then it becomes a cycle.
I have run the above program in VC8.0 and it generates no errors.
It doesn't accord with my expectation. I wonder why.
Any explanations or opinions will be appreciated.
HaoZhuo
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Tue Sep 19, 2006 1:13 am Post subject: Re: Why doesn't shared_ptr generate a cycle? |
|
|
hzhuo1 (AT) gmail (DOT) com wrote:
| Quote: | In the main function , we create two dynamic objects *a and *b. *a
contains a shared_ptr<B> which points to *b, whereas *b contains a
shared_ptr<A> which points to *a. Before the main function returns ,it
should call A and B's destruction functions. But since A contains a
shared_ptr<B>,calling to A's destruction function will cause a call to
B's destruction function. Then it becomes a cycle.
|
Yup.
| Quote: | I have run the above program in VC8.0 and it generates no errors.
It doesn't accord with my expectation. I wonder why.
Any explanations or opinions will be appreciated.
|
Creating a cycle is not an error. However, if you don't do something to
break the cycle, you get a resource leak. On the other hand, the code in
the message doesn't execute any destructors at all, so even if there
weren't a cycle there would be a resource leak.
--
-- Pete
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Thomas J. Gritzan Guest
|
Posted: Tue Sep 19, 2006 1:13 am Post subject: Re: Why doesn't shared_ptr generate a cycle? |
|
|
hzhuo1 (AT) gmail (DOT) com schrieb:
[two objects, each one holds a shared_ptr of the other]
| Quote: | In the main function , we create two dynamic objects *a and *b. *a
contains a shared_ptr<B> which points to *b, whereas *b contains a
shared_ptr<A> which points to *a. Before the main function returns ,it
should call A and B's destruction functions. But since A contains a
shared_ptr<B>,calling to A's destruction function will cause a call to
B's destruction function. Then it becomes a cycle.
|
There is a valid shared_ptr object to a in b, so a will never be
destroyed (the reference count won't drop to zero). There is a valid
shared_ptr in b to a, so b will never be destroyed. That's a cycle. And
two memory leaks.
| Quote: | I have run the above program in VC8.0 and it generates no errors.
It doesn't accord with my expectation. I wonder why.
Any explanations or opinions will be appreciated.
|
Avoid cyclic references with shared_ptr. Think about your ownership
requirements. Use weak_ptr to break the cyclic references.
--
Thomas
http://www.netmeister.org/news/learn2quote.html
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Jens Theisen Guest
|
Posted: Tue Sep 19, 2006 1:15 am Post subject: Re: Why doesn't shared_ptr generate a cycle? |
|
|
"hzhuo1 (AT) gmail (DOT) com" <hzhuo1 (AT) gmail (DOT) com> writes:
| Quote: | Then it becomes a cycle.
|
I becomes a cycle, but there is no delete that could trigger
destruction.
What would you expect?
Jens
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
hzhuo1@gmail.com Guest
|
Posted: Tue Sep 19, 2006 10:01 pm Post subject: Re: Why doesn't shared_ptr generate a cycle? |
|
|
Pete Becker wrote:
| Quote: | Creating a cycle is not an error. However, if you don't do something to
break the cycle, you get a resource leak. On the other hand, the code in
the message doesn't execute any destructors at all, so even if there
weren't a cycle there would be a resource leak.
I feel sorry that I didn't trigger the destructors in the main |
function. This time I add a delete sentence to make the main function
look like the following:
int main(){
A *a= new A;
B *b= new B(a);
a->create(b);
delete a;
return 1;
}
When I execute the new program,it gives a pop-up message saying "Debug
assertion failed". Is it the expected error caused by the shared_ptr
cycle? And can this kind of error be corrected with weak_ptr?
Thanks.
HaoZhuo
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
aa Guest
|
Posted: Tue Sep 19, 2006 10:13 pm Post subject: Re: Why doesn't shared_ptr generate a cycle? |
|
|
Pete Becker wrote:
| Quote: | Creating a cycle is not an error. However, if you don't do something to
break the cycle, you get a resource leak. On the other hand, the code in
the message doesn't execute any destructors at all, so even if there
weren't a cycle there would be a resource leak.
|
Sorry, but I don't get where the ref cycle should come from. If these
were intrusive_ptr, then ok, I'd see the cycle, but passing around
naked pointers and assign them to shared_ptr cannot generate cycles.
What am I missing here?
cheers,
aa
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Tue Sep 19, 2006 11:10 pm Post subject: Re: Why doesn't shared_ptr generate a cycle? |
|
|
hzhuo1 (AT) gmail (DOT) com wrote:
| Quote: | Pete Becker wrote:
Creating a cycle is not an error. However, if you don't do something to
break the cycle, you get a resource leak. On the other hand, the code in
the message doesn't execute any destructors at all, so even if there
weren't a cycle there would be a resource leak.
I feel sorry that I didn't trigger the destructors in the main
function. This time I add a delete sentence to make the main function
look like the following:
int main(){
A *a= new A;
B *b= new B(a);
a->create(b);
delete a;
return 1;
}
When I execute the new program,it gives a pop-up message saying "Debug
assertion failed". Is it the expected error caused by the shared_ptr
cycle? And can this kind of error be corrected with weak_ptr?
|
This runtime error does not depend on the details of shared_ptr vs.
weak_ptr. The code deletes a; this runs A's destructor, which runs the
destructor for a's shared_ptr object, which deletes b; this runs B's
destructor, which runs the destructor for b's shared_ptr object, which
deletes a for the second time. You'd have the same problem if A and B
held raw pointers and their destructors just deleted the pointer.
But there's another important problem here: the code uses an A* in main
and a shared_ptr<A> in the B object to manage the same A object. That's
going to cause trouble. Use one or the other. If you need automatic
resource management, in general you shouldn't be messing with raw pointers.
A needs to be changed to handle a shared_ptr<B>:
class A
{
shared_ptr<B> x;
public:
void create(shared_ptr<B> bb) { x = bb; }
};
B needs to be changed to handle a shared_ptr<A>:
class B
{
shared_ptr<A> y;
public:
B(shared_ptr<A> aa) : y(aa) {};
};
and now we can change main to get back to something like your original code:
int main()
{
shared_ptr<A> a(new A);
shared_ptr<B> b(new B(a));
a->create(b);
return 0;
}
Now you've got a cycle: the destructors for the two shared_ptr objects
in main will run, but because the two resources each hold shared_ptr
objects pointing to the other, the new'ed resources won't be destroyed.
To break the cycle, one of the two links has to be something other than
a shared_ptr object. If you change B by changing the type of y from
shared_ptr<A> to weak_ptr<A> that will fix the problem. If you change B
by changing the type of y from shared_ptr<A> to A* that will also fix
the problem. For this example, either approach works fine. In more
complex situations, the choice depends on what else is going on with
resource management.
--
-- Pete
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Tue Sep 19, 2006 11:13 pm Post subject: Re: Why doesn't shared_ptr generate a cycle? |
|
|
aa wrote:
| Quote: | Pete Becker wrote:
Creating a cycle is not an error. However, if you don't do something to
break the cycle, you get a resource leak. On the other hand, the code in
the message doesn't execute any destructors at all, so even if there
weren't a cycle there would be a resource leak.
Sorry, but I don't get where the ref cycle should come from. If these
were intrusive_ptr, then ok, I'd see the cycle, but passing around
naked pointers and assign them to shared_ptr cannot generate cycles.
What am I missing here?
|
The call a->create(b) makes the cycle. The A object has a shared_ptr
object that points to the B object; the B object has a shared_ptr object
that points to the A object. Neither reference count will go to zero, so
the automatic resource management that you get from the use of
shared_ptr won't work.
--
-- Pete
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|