Boost logo

Boost :

From: Ananda Tallur (anand_at_[hidden])
Date: 2006-03-24 12:57:16


Hello,

Originally, I had discovered a problem when using
boost::unit_test_framework, for which I have already posted.
But, by further analysing the problem, I could come out to a simple
program, using only boost shared pointers, and which fails :
-> on Mac OS X 10.4
-> when compiled with gcc 4.0.1 (coming with XCode 2.2.1), or gcc 4.1
(delivered by darwin ports)
-> with optimisations : at least -O, or -O1, or -O2,etc... It works
correctly with -O0
-> using either boost 1.33.1, 1.33.0, or 1.32.0

Below is the sample test program :

--- macosx_gcc4problem.cpp ---
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost;

struct A {
    int value;
    ~A ()
    {
       std::cout << "A destructor" << std::endl << std::flush;
    }
};

struct B
{
     B (shared_ptr <A> val)
     : a (val) {}

     shared_ptr <A> a;
};

struct C {
     C (B val)
     : b (val) {}

    B b;
};

struct D
{
    D (C val)
    : c (val)
    {}
    C c;
};

D create ()
{
    boost::shared_ptr <A> a (new A);
    a->value = 12345;
    return D (C (B (a)));
}

int main (int argc, char * argv [])
{
    D d = create ();
    std::cout << "value = " << d.c.b.a->value << std::endl <<
std::flush;
    return 0;
}
--- macosx_gcc4problem.cpp ---

To compile it :
g++-4.0 -O2 -I <path-to-boost-includes> macosx_gcc4problem.cpp -o
macosx_gcc4problem

Output :
When run, the value displayed is 13691, instead of 12345 as it should.

Analysis :
-> there is a problem in shared_ptr reference counting, in line :
return D (C (B (a)));
     Just after D creation, the reference counter is at 1, instead of
2 as it should.
     And when leaving create () function, the automatic variable a is
detroyed, which changes the reference counter to 0 and detroys the A
object.

     In main function after call to create (), the reference counter
should be of 1, and the object A should be available on the heap.
     But it has already been destroyed, leading to an incorrect
result being displayed.
     In worst cases, a segmentation fault may happen.

Remark : if changing the constructor of B, so that a const reference
to the shared_ptr is passed, instead of the shared_ptr itself, it
works :

---
struct B
{
     B (const shared_ptr <A> &val)
     : a (val) {}
---
To further investigate the problem, it may be needed to analyse the  
assembly code generated by the gcc 4 compiler.
The problem is clearly in the line : return D (C (B (a)));
There may be a problem with management of temporary variables,  
combined with optimisations.
I require the help of other developpers working on Mac OS X, because  
I think this problem could concern many of us.
I guess It is likely that the problem is not specifically caused by  
boost, but may rather be a gcc 4 compiler problem on Mac OS X.
Thanks
Anand

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