Serious problem with gcc 4 on Mac OS X, when using boost:shared_ptr

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

Ananda Tallur wrote:
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 ---
[...] This issue has already been reported, along with a fix, by Howard Hinnant: http://lists.boost.org/Archives/boost/2006/03/102088.php http://lists.boost.org/Archives/boost/2006/03/102122.php http://lists.boost.org/Archives/boost/2006/03/102134.php and the upcoming 1.34 release will no longer suffer from it. Thank you very much for taking the time to simplify the failing example. I've reformatted it a bit as a test case. If you verify that it still fails for you, I'll include it in the regression tests. #include <boost/shared_ptr.hpp> #include <boost/detail/lightweight_test.hpp> struct A { int value; }; struct B { B( boost::shared_ptr<A> val ): a( val ) {} boost::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() { D d = create(); BOOST_TEST( d.c.b.a->value == 12345 ); return boost::report_errors(); }
participants (2)
-
Ananda Tallur
-
Peter Dimov