|
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