$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Gary Powell (Gary.Powell_at_[hidden])
Date: 2001-05-16 14:05:25
This bug also appears to be in shared_array::operator=()
> -----Original Message-----
> From:	Greg Colvin [SMTP:gcolvin_at_[hidden]]
> Sent:	Wednesday, May 16, 2001 7:53 AM
> To:	boost_at_[hidden]
> Subject:	Re: [boost] Problem with shared_ptr
> 
> From: Beman Dawes <bdawes_at_[hidden]>
> > At 03:29 AM 5/16/2001, Thomas Maeder wrote:
> > 
> >  >This problem report is a result of a discussion in
> >  >news://newsgroups.borland.com/borland.public.cppbuilder.language
> >  >
> >  >The following program demonstrates it, using boost 1.21.1 and gcc
> 2.95.3:
> >  >
> >  >#include <iostream>
> >  >
> >  >#include "boost/smart_ptr.hpp"
> >  >
> >  >struct S
> >  >{
> >  >    ~S()
> >  >    {
> >  >      std::cout << "~S()\n";
> >  >    }
> >  >
> >  >    boost::shared_ptr<S> next;
> >  >};
> >  >
> >  >int main()
> >  >{
> >  >  boost::shared_ptr<S> head(new S);
> >  >  head->next.reset(new S);
> >  >  std::cout << "before assignment\n";
> >  >  head = head->next;
> >  >  std::cout << "after assignment\n";
> >  >}
> >  >
> >  >The output is
> >  >
> >  >before assginment
> >  >~S()
> >  >~S()
> >  >after assginment
> > 
> > Ouch!
> 
> Amen.
> 
> >  >while one would expect it to be
> >  >
> >  >before assignment
> >  >~S()
> >  >after assignment
> >  >~S()
> >  >
> >  >The reason is that the shared_ptr copy-assignment operator first
> reduces
> >  >the reference count of the previously owned object and only then 
> > increases
> >  >that of the newly owned object; if both objects are the same, strange
> >  >things happen.
> > 
> > It isn't really a case of both objects being the same, but that the
> right 
> > hand object is transitively dependent on the left hand object.
> > 
> > The code causing the problem is:
> > 
> >     void share(T* rpx, long* rpn) {
> >        if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0
> >           dispose();
> >           px = rpx;
> >           ++*(pn = rpn);
> >        }
> > 
> > My first reaction is to change it to:
> > 
> >     void share(T* rpx, long* rpn) {
> >        if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0
> >           ++*rpn; // done before dispose() in case rpn transitively
> >                   // dependent on *this (bug reported by Thomas Maeder)
> >           dispose();
> >           px = rpx;
> >           pn = rpn;
> >        }
> 
> This looks right to me.
> 
>  
> > I'll have give it a bit more thought.  Greg?  Also do some testing.  The
> 
> > test program needs updating anyhow.
> >
> > Thanks for the bug report.
> > 
> > --Beman
>