problem with shared_ptr

I am using boost share_ptr and I have a very strange problem. it looks to me more like a compiler problem but since it is a boost code I decided to post it here. I haven't succeeded to creating a small example which I can post here and demonstrate the problem (I know it is hard to help that way but I am working on creating an example) so I will just describe it. The symptom is that the shared_ptr call the delete on a random pointer. Going into the shared_ptr and shared_count objects, I sow that the ptr field of sp_counted_base_impl has a wrong value. I have added prints out all over the code and saw that inside the constructor of sp_counted_base_impl the value is set correctly but on the return when I try to look at the value and it is a wrong value. adding some more prints I saw that inside the shared_count constructor: template<class P, class D> shared_count(P p, D d) when casting pi_ to (sp_counted_base_impl<P, D>*) and calling a member function, the sizeof(*this) in side the member function is not the same every time (resulting with a different address to ptr and thus different value). the problem occurs only when compiling -O I am attaching the two file I have changes (shared_count.hpp is from boost/detail/) and the prints there created. I am sorry I can't supplied a complete example, this problems can just disappear when I remove any object file from the compilation. my configuration: compiler: gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) OS: Red Hat Linux release 8.0 (Psyche) boost: boost-1.30.2 any help will be appreciated #ifndef BOOST_SHARED_PTR_HPP_INCLUDED #define BOOST_SHARED_PTR_HPP_INCLUDED // // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // #include <boost/config.hpp> // for broken compiler workarounds #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) #include <boost/detail/shared_ptr_nmt.hpp> #else #include <boost/assert.hpp> #include <boost/checked_delete.hpp> #include <boost/throw_exception.hpp> #include <boost/detail/shared_count.hpp> #include <boost/detail/workaround.hpp> #include <memory> // for std::auto_ptr #include <algorithm> // for std::swap #include <functional> // for std::less #include <typeinfo> // for std::bad_cast #include <iosfwd> // for std::basic_ostream #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) # pragma warning(disable:4284) // odd return type for operator-> #endif namespace boost { template<class T> class weak_ptr; template<class T> class enable_shared_from_this; namespace detail { struct static_cast_tag {}; struct dynamic_cast_tag {}; struct polymorphic_cast_tag {}; template<class T> struct shared_ptr_traits { typedef T & reference; }; template<> struct shared_ptr_traits<void> { typedef void reference; }; #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) template<> struct shared_ptr_traits<void const> { typedef void reference; }; #endif // enable_shared_from_this support template<class T, class Y> void sp_enable_shared_from_this(boost::enable_shared_from_this<T> * pe, Y * px, shared_count const & pn) { if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn); } inline void sp_enable_shared_from_this(void const *, void const *, shared_count const &) { } } // namespace detail // // shared_ptr // // An enhanced relative of scoped_ptr with reference counted copy semantics. // The object pointed to is deleted when the last shared_ptr pointing to it // is destroyed or reset. // template<class T> class shared_ptr { private: // Borland 5.5.1 specific workaround typedef shared_ptr<T> this_type; public: typedef T element_type; typedef T value_type; typedef T * pointer; typedef typename detail::shared_ptr_traits<T>::reference reference; shared_ptr(): px(0), pn() // never throws in 1.30+ { } template<class Y> explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete // Eyal Fink changed that!!! //shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete { print_ptrs(); detail::sp_enable_shared_from_this(p, p, pn); print_ptrs(); } void print_ptrs() { //cout <<"px= "<<px<<" ptr= "<< pn.get_ptr(p, checked_deleter<Y>())<<endl; } // ~shared_ptr() // { // print_ptrs(); // } // // Requirements: D's copy constructor must not throw // // shared_ptr will release p by calling d(p) // template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d) { detail::sp_enable_shared_from_this(p, p, pn); } // generated copy constructor, assignment, destructor are fine... // except that Borland C++ has a bug, and g++ with -Wsynth warns #if defined(__BORLANDC__) || defined(__GNUC__) shared_ptr & operator=(shared_ptr const & r) // never throws { px = r.px; pn = r.pn; // shared_count::op= doesn't throw return *this; } #endif template<class Y> explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw { // it is now safe to copy r.px, as pn(r.pn) did not throw px = r.px; } template<class Y> shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws { } template<class Y> shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn) { } template<class Y> shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) { if(px == 0) // need to allocate new counter -- the cast failed { pn = detail::shared_count(); } } template<class Y> shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) { if(px == 0) { boost::throw_exception(std::bad_cast()); } } #ifndef BOOST_NO_AUTO_PTR template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn() { Y * tmp = r.get(); pn = detail::shared_count(r); detail::sp_enable_shared_from_this(tmp, tmp, pn); } #endif #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) // never throws { px = r.px; pn = r.pn; // shared_count::op= doesn't throw return *this; } #endif #ifndef BOOST_NO_AUTO_PTR template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r) { this_type(r).swap(*this); return *this; } #endif void reset() // never throws in 1.30+ { this_type().swap(*this); } template<class Y> void reset(Y * p) // Y must be complete { BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors this_type(p).swap(*this); } template<class Y, class D> void reset(Y * p, D d) { this_type(p, d).swap(*this); } reference operator* () const // never throws { BOOST_ASSERT(px != 0); return *px; } T * operator-> () const // never throws { BOOST_ASSERT(px != 0); return px; } T * get() const // never throws { return px; } // implicit conversion to "bool" #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const { return px != 0; } #else typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws { return px == 0? 0: &this_type::get; } #endif // operator! is redundant, but some compilers need it bool operator! () const // never throws { return px == 0; } bool unique() const // never throws { return pn.unique(); } long use_count() const // never throws { return pn.use_count(); } void swap(shared_ptr<T> & other) // never throws { std::swap(px, other.px); pn.swap(other.pn); } template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const { return pn < rhs.pn; } void * _internal_get_deleter(std::type_info const & ti) const { return pn.get_deleter(ti); } // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: template<class Y> friend class shared_ptr; template<class Y> friend class weak_ptr; #endif T * px; // contained pointer detail::shared_count pn; // reference counter }; // shared_ptr template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) { return a.get() == b.get(); } template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) { return a.get() != b.get(); } #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 // Resolve the ambiguity between our op!= and the one in rel_ops template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) { return a.get() != b.get(); } #endif template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) { return a._internal_less(b); } template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) { a.swap(b); } template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) { return shared_ptr<T>(r, detail::static_cast_tag()); } template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) { return shared_ptr<T>(r, detail::dynamic_cast_tag()); } // shared_*_cast names are deprecated. Use *_pointer_cast instead. template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r) { return shared_ptr<T>(r, detail::static_cast_tag()); } template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r) { return shared_ptr<T>(r, detail::dynamic_cast_tag()); } template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r) { return shared_ptr<T>(r, detail::polymorphic_cast_tag()); } template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r) { BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get()); return shared_static_cast<T>(r); } // get_pointer() enables boost::mem_fn to recognize shared_ptr template<class T> inline T * get_pointer(shared_ptr<T> const & p) { return p.get(); } // operator<< #if defined(__GNUC__) && (__GNUC__ < 3) template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p) { os << p.get(); return os; } #else # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p) # else template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p) # endif { os << p.get(); return os; } #endif // get_deleter (experimental) #if defined(__GNUC__) && (__GNUC__ < 3) // g++ 2.9x doesn't allow static_cast<X const *>(void *) template<class D, class T> D * get_deleter(shared_ptr<T> const & p) { void const * q = p._internal_get_deleter(typeid(D)); return const_cast<D *>(static_cast<D const *>(q)); } #else template<class D, class T> D * get_deleter(shared_ptr<T> const & p) { return static_cast<D *>(p._internal_get_deleter(typeid(D))); } #endif } // namespace boost #ifdef BOOST_MSVC # pragma warning(pop) #endif #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED #define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif // // detail/shared_count.hpp // // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // #include <boost/config.hpp> #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. #endif #include <boost/checked_delete.hpp> #include <boost/throw_exception.hpp> #include <boost/detail/lightweight_mutex.hpp> #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) #include <boost/detail/quick_allocator.hpp> #endif #include <memory> // std::auto_ptr, std::allocator #include <functional> // std::less #include <exception> // std::exception #include <new> // std::bad_alloc #include <typeinfo> // std::type_info in get_deleter #include <cstddef> // std::size_t #ifdef __BORLANDC__ # pragma warn -8026 // Functions with excep. spec. are not expanded inline # pragma warn -8027 // Functions containing try are not expanded inline #endif namespace boost { // Debug hooks #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn); void sp_array_constructor_hook(void * px); void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn); void sp_array_destructor_hook(void * px); #endif // The standard library that comes with Borland C++ 5.5.1 // defines std::exception and its members as having C calling // convention (-pc). When the definition of bad_weak_ptr // is compiled with -ps, the compiler issues an error. // Hence, the temporary #pragma option -pc below. The version // check is deliberately conservative. #if defined(__BORLANDC__) && __BORLANDC__ == 0x551 # pragma option push -pc #endif class bad_weak_ptr: public std::exception { public: virtual char const * what() const throw() { return "boost::bad_weak_ptr"; } }; #if defined(__BORLANDC__) && __BORLANDC__ == 0x551 # pragma option pop #endif namespace detail { class sp_counted_base { private: typedef detail::lightweight_mutex mutex_type; public: sp_counted_base(): use_count_(1), weak_count_(1) { } virtual ~sp_counted_base() // nothrow { } virtual void *get_ptr() { exit(-1); } virtual void set_ptr(void *ptr) { //cout <<"we are not supposed to be here!"<<endl; exit(-1); } // dispose() is called when use_count_ drops to zero, to release // the resources managed by *this. virtual void dispose() = 0; // nothrow // destruct() is called when weak_count_ drops to zero. virtual void destruct() // nothrow { delete this; } virtual void * get_deleter(std::type_info const & ti) = 0; void add_ref() { #if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::bad_weak_ptr()); ++use_count_; ++weak_count_; } void release() // nothrow { { #if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif long new_use_count = --use_count_; if(new_use_count != 0) { --weak_count_; return; } } dispose(); weak_release(); } void weak_add_ref() // nothrow { #if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif ++weak_count_; } void weak_release() // nothrow { long new_weak_count; { #if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif new_weak_count = --weak_count_; } if(new_weak_count == 0) { destruct(); } } long use_count() const // nothrow { #if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif return use_count_; } private: sp_counted_base(sp_counted_base const &); sp_counted_base & operator= (sp_counted_base const &); // inv: use_count_ <= weak_count_ long use_count_; long weak_count_; #if defined(BOOST_HAS_THREADS) mutable mutex_type mtx_; #endif }; #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int) { boost::sp_scalar_constructor_hook(px, sizeof(T), pn); } template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int) { boost::sp_array_constructor_hook(px); } template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long) { } template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int) { boost::sp_scalar_destructor_hook(px, sizeof(T), pn); } template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int) { boost::sp_array_destructor_hook(px); } template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long) { } #endif // // Borland's Codeguard trips up over the -Vx- option here: // #ifdef __CODEGUARD__ # pragma option push -Vx- #endif template<class P, class D> class sp_counted_base_impl: public sp_counted_base { private: D del; // copy constructor must not throw P ptr; // copy constructor must not throw sp_counted_base_impl(sp_counted_base_impl const &); sp_counted_base_impl & operator= (sp_counted_base_impl const &); typedef sp_counted_base_impl<P, D> this_type; public: // pre: initial_use_count <= initial_weak_count, d(p) must not throw sp_counted_base_impl(P p, D d): ptr(p), del(d) { cout <<"IN sp_counted_base_impl ocnstructro ptr="<<ptr<<" p="<<p<<endl; #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) detail::cbi_call_constructor_hook(this, p, d, 0); #endif cout <<"sizeof(*this)= "<<sizeof(*this)<<endl; cout <<"IN sp_counted_base_impl end ocnstructro ptr=" <<ptr<<" ptr addr: "<<&ptr<<" p="<<p<<endl; } virtual void dispose() // nothrow { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) detail::cbi_call_destructor_hook(this, ptr, del, 0); #endif //cout <<"IN boost::dispose ptr="<<ptr<<endl; del(ptr); } P get_ptr() { cout <<"this= "<<this<<" ptr in get_ptr= "<<ptr<<endl; cout <<"sizeof(*this)= "<<sizeof(*this)<<endl; cout <<"ptr addr: "<<&ptr<<endl; return ptr; } void set_ptr(P _ptr) { cout <<"this= "<<this<<" setting ptr to: "<<_ptr<<endl; ptr=_ptr; cout <<"sizeof(*this)= "<<sizeof(*this)<<endl; cout <<"ptr= "<<ptr<<endl; cout <<"ptr addr: "<<&ptr<<endl; } virtual void * get_deleter(std::type_info const & ti) { return ti == typeid(D)? &del: 0; } #if defined(BOOST_SP_USE_STD_ALLOCATOR) void * operator new(std::size_t) { return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0)); } void operator delete(void * p) { std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1); } #endif #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) void * operator new(std::size_t) { return quick_allocator<this_type>::alloc(); } void operator delete(void * p) { quick_allocator<this_type>::dealloc(p); } #endif }; #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) int const shared_count_id = 0x2C35F101; int const weak_count_id = 0x298C38A4; #endif class weak_count; class shared_count { private: sp_counted_base * pi_; #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) int id_; #endif friend class weak_count; public: shared_count(): pi_(0) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { } template<class P, class D> shared_count(P p, D d): pi_(0) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { cout <<"in shared_count: p= "<<p<<endl; #ifndef BOOST_NO_EXCEPTIONS try { pi_ = new sp_counted_base_impl<P, D>(p, d); cout <<"return from new sp_counted_base_impl1: p= "<<p << " pi_->ptr= "<<pi_->get_ptr()<<endl; } catch(...) { d(p); // delete p throw; } #else pi_ = new sp_counted_base_impl<P, D>(p, d); cout <<"return from new sp_counted_base_impl2: p= "<<p << " pi_->ptr= "<<pi_->get_ptr()<<endl; if(pi_ == 0) { d(p); // delete p boost::throw_exception(std::bad_alloc()); } #endif ((sp_counted_base_impl<P, D>*)pi_)->set_ptr(p); cout <<"after fix: pi_->ptr= " <<((sp_counted_base_impl<P, D>*)pi_)->get_ptr()<<endl; cout <<"end of shared_count: ptr= "<<pi_->get_ptr()<<endl; } #ifndef BOOST_NO_AUTO_PTR // auto_ptr<Y> is special cased to provide the strong guarantee template<class Y> explicit shared_count(std::auto_ptr<Y> & r): pi_(new sp_counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>())) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { r.release(); } #endif ~shared_count() // nothrow { if(pi_ != 0) pi_->release(); #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) id_ = 0; #endif } shared_count(shared_count const & r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { if(pi_ != 0) pi_->add_ref(); } explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 shared_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; if(tmp != 0) tmp->add_ref(); if(pi_ != 0) pi_->release(); pi_ = tmp; return *this; } void swap(shared_count & r) // nothrow { sp_counted_base * tmp = r.pi_; r.pi_ = pi_; pi_ = tmp; } long use_count() const // nothrow { return pi_ != 0? pi_->use_count(): 0; } bool unique() const // nothrow { return use_count() == 1; } friend inline bool operator==(shared_count const & a, shared_count const & b) { return a.pi_ == b.pi_; } friend inline bool operator<(shared_count const & a, shared_count const & b) { return std::less<sp_counted_base *>()(a.pi_, b.pi_); } void * get_deleter(std::type_info const & ti) const { return pi_? pi_->get_deleter(ti): 0; } template<class P, class D> P get_ptr() { return pi_?((sp_counted_base_impl<P, D>*)pi_)->get_ptr() : 0; } void set_ptr(void *ptr) { if(pi_) pi_->set_ptr(ptr); } }; #ifdef __CODEGUARD__ # pragma option pop #endif class weak_count { private: sp_counted_base * pi_; #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) int id_; #endif friend class shared_count; public: weak_count(): pi_(0) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(weak_count_id) #endif { } weak_count(shared_count const & r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { if(pi_ != 0) pi_->weak_add_ref(); } weak_count(weak_count const & r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { if(pi_ != 0) pi_->weak_add_ref(); } ~weak_count() // nothrow { if(pi_ != 0) pi_->weak_release(); #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) id_ = 0; #endif } weak_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; if(tmp != 0) tmp->weak_add_ref(); if(pi_ != 0) pi_->weak_release(); pi_ = tmp; return *this; } weak_count & operator= (weak_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; if(tmp != 0) tmp->weak_add_ref(); if(pi_ != 0) pi_->weak_release(); pi_ = tmp; return *this; } void swap(weak_count & r) // nothrow { sp_counted_base * tmp = r.pi_; r.pi_ = pi_; pi_ = tmp; } long use_count() const // nothrow { return pi_ != 0? pi_->use_count(): 0; } friend inline bool operator==(weak_count const & a, weak_count const & b) { return a.pi_ == b.pi_; } friend inline bool operator<(weak_count const & a, weak_count const & b) { return std::less<sp_counted_base *>()(a.pi_, b.pi_); } }; inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { if(pi_ != 0) { pi_->add_ref(); } else { boost::throw_exception(boost::bad_weak_ptr()); } } } // namespace detail } // namespace boost #ifdef __BORLANDC__ # pragma warn .8027 // Functions containing try are not expanded inline # pragma warn .8026 // Functions with excep. spec. are not expanded inline #endif #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED in shared_count: p= 0x8127738 IN sp_counted_base_impl ocnstructro ptr=0x8127738 p=0x8127738 sizeof(*this)= 44 IN sp_counted_base_impl end ocnstructro ptr=0x8127738 ptr addr: 0x8127fd8 p=0x81 27738 this= 0x8127fb0 ptr in get_ptr= 0 sizeof(*this)= 20 ptr addr: 0x8127fc0 return from new sp_counted_base_impl1: p= 0x8127738 pi_->ptr= 0 this= 0x8127fb0 setting ptr to: 0x8127738 sizeof(*this)= 44 ptr= 0x8127738 ptr addr: 0x8127fd8 this= 0x8127fb0 ptr in get_ptr= 0 sizeof(*this)= 20 ptr addr: 0x8127fc0 after fix: pi_->ptr= 0 this= 0x8127fb0 ptr in get_ptr= 0 sizeof(*this)= 20 ptr addr: 0x8127fc0 end of shared_count: ptr= 0

Eyal Fink wrote:
I am using boost share_ptr and I have a very strange problem. it looks to me more like a compiler problem but since it is a boost code I decided to post it here. I haven't succeeded to creating a small example which I can post here and demonstrate the problem (I know it is hard to help that way but I am working on creating an example) so I will just describe it. The symptom is that the shared_ptr call the delete on a random pointer. Going into the shared_ptr and shared_count objects, I sow that the ptr field of sp_counted_base_impl has a wrong value. I have added prints out all over the code and saw that inside the constructor of sp_counted_base_impl the value is set correctly but on the return when I try to look at the value and it is a wrong value. adding some more prints I saw that inside the shared_count constructor: template<class P, class D> shared_count(P p, D d) when casting pi_ to (sp_counted_base_impl<P, D>*) and calling a member function, the sizeof(*this) in side the member function is not the same every time (resulting with a different address to ptr and thus different value). the problem occurs only when compiling -O
Very odd; looks like either optimizer problem or ABI mismatch. Have you tried g++ 3.2.3 or 3.3.2?

Peter Dimov wrote:
Eyal Fink wrote:
I am using boost share_ptr and I have a very strange problem. it looks to me more like a compiler problem but since it is a boost code I decided to post it here. I haven't succeeded to creating a small example which I can post here and demonstrate the problem (I know it is hard to help that way but I am working on creating an example) so I will just describe it. The symptom is that the shared_ptr call the delete on a random pointer. Going into the shared_ptr and shared_count objects, I sow that the ptr field of sp_counted_base_impl has a wrong value. I have added prints out all over the code and saw that inside the constructor of sp_counted_base_impl the value is set correctly but on the return when I try to look at the value and it is a wrong value. adding some more prints I saw that inside the shared_count constructor: template<class P, class D> shared_count(P p, D d) when casting pi_ to (sp_counted_base_impl<P, D>*) and calling a member function, the sizeof(*this) in side the member function is not the same every time (resulting with a different address to ptr and thus different value). the problem occurs only when compiling -O
Very odd; looks like either optimizer problem or ABI mismatch. Have you tried g++ 3.2.3 or 3.3.2?
I have not tried newer versions yet (I have tried 2.9.5 and it happens there as well) what is ABI mismatch?
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Eyal Fink
-
Peter Dimov