Boost logo

Boost :

From: Beman Dawes (bdawes_at_[hidden])
Date: 2001-05-16 06:56:53


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!

>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;
       }

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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk