What are the steps to reproduce the problem? I build that source file with -O0, 1, 2 and 3, and in all of them I get "42" as the output.
- Alon On Sat, Apr 4, 2015 at 7:12 AM, <[email protected]> wrote: > OK the following self contained code (*not* calling any boost headers) is > fine with O0 or O1, but not with O2 or O3. The function which I am > exporting is : > > extern "C" { > double test(void) { > boost::shared_ptr<int> y = boost::shared_ptr<int>(new int(42)); > return *y; > } > } > > The invocation of "dispose()" and "weak_release()" in > "sp_counted_base::release" is what is causing the problems : > > #include <atomic> > #include <iostream> > #include <vector> > using namespace std; > > namespace boost > { > > namespace core > { > > > class typeinfo > { > private: > > typeinfo( typeinfo const& ); > typeinfo& operator=( typeinfo const& ); > > char const * name_; > > public: > > explicit typeinfo( char const * name ): name_( name ) > { > } > > bool operator==( typeinfo const& rhs ) const > { > return this == &rhs; > } > > bool operator!=( typeinfo const& rhs ) const > { > return this != &rhs; > } > > bool before( typeinfo const& rhs ) const > { > return std::less< typeinfo const* >()( this, &rhs ); > } > > char const* name() const > { > return name_; > } > }; > > > }//namespace core > > template<class T> class shared_ptr; > template<class T> class enable_shared_from_this; > > template<class T> inline void checked_delete(T * x) > { > // intentionally complex - simplification causes regressions > typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; > (void) sizeof(type_must_be_complete); > delete x; > } > > namespace detail > { > > typedef boost::core::typeinfo sp_typeinfo; > > inline void atomic_increment( std::atomic_int_least32_t * pw ) > { > pw->fetch_add( 1, std::memory_order_relaxed ); > } > > inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw > ) > { > return pw->fetch_sub( 1, std::memory_order_acq_rel ); > } > > inline std::int_least32_t atomic_conditional_increment( > std::atomic_int_least32_t * pw ) > { > // long r = *pw; > // if( r != 0 ) ++*pw; > // return r; > > std::int_least32_t r = pw->load( std::memory_order_relaxed ); > > for( ;; ) > { > if( r == 0 ) > { > return r; > } > > if( pw->compare_exchange_weak( r, r + 1, > std::memory_order_relaxed, std::memory_order_relaxed ) ) > { > return r; > } > } > } > > class sp_counted_base > { > private: > > sp_counted_base( sp_counted_base const & ); > sp_counted_base & operator= ( sp_counted_base const & ); > > std::atomic_int_least32_t use_count_; // #shared > std::atomic_int_least32_t weak_count_; // #weak + (#shared != 0) > > public: > > sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) > { > } > > virtual ~sp_counted_base() // nothrow > { > } > > // dispose() is called when use_count_ drops to zero, to release > // the resources managed by *this. > > virtual void dispose() = 0; // nothrow > > // destroy() is called when weak_count_ drops to zero. > > virtual void destroy() // nothrow > { > delete this; > } > > virtual void * get_deleter( sp_typeinfo const & ti ) = 0; > virtual void * get_untyped_deleter() = 0; > > void add_ref_copy() > { > atomic_increment( &use_count_ ); > } > > bool add_ref_lock() // true on success > { > return atomic_conditional_increment( &use_count_ ) != 0; > } > > void release() // nothrow > { > if( atomic_decrement( &use_count_ ) == 1 ) > { > dispose(); > weak_release(); > } > } > > void weak_add_ref() // nothrow > { > atomic_increment( &weak_count_ ); > } > > void weak_release() // nothrow > { > if( atomic_decrement( &weak_count_ ) == 1 ) > { > destroy(); > } > } > > long use_count() const // nothrow > { > return use_count_.load( std::memory_order_acquire ); > } > }; > > > template<class X> class sp_counted_impl_p: public sp_counted_base > { > private: > > X * px_; > > sp_counted_impl_p( sp_counted_impl_p const & ); > sp_counted_impl_p & operator= ( sp_counted_impl_p const & ); > > typedef sp_counted_impl_p<X> this_type; > > public: > > explicit sp_counted_impl_p( X * px ): px_( px ) > { > #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) > boost::sp_scalar_constructor_hook( px, sizeof(X), this ); > #endif > } > > virtual void dispose() // nothrow > { > #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) > boost::sp_scalar_destructor_hook( px_, sizeof(X), this ); > #endif > boost::checked_delete( px_ ); > } > > virtual void * get_deleter( detail::sp_typeinfo const & ) > { > return 0; > } > > virtual void * get_untyped_deleter() > { > return 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 > }; > > class shared_count > { > private: > > sp_counted_base * pi_; > > public: > > void swap(shared_count & r) // nothrow > { > sp_counted_base * tmp = r.pi_; > r.pi_ = pi_; > pi_ = tmp; > } > > shared_count(): pi_(0) // nothrow > #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) > , id_(shared_count_id) > #endif > { > } > > template<class Y> explicit shared_count( Y * p ): pi_( 0 ) > #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) > , id_(shared_count_id) > #endif > { > #ifndef BOOST_NO_EXCEPTIONS > > try > { > pi_ = new sp_counted_impl_p<Y>( p ); > } > catch(...) > { > boost::checked_delete( p ); > throw; > } > > #else > > pi_ = new sp_counted_impl_p<Y>( p ); > > if( pi_ == 0 ) > { > boost::checked_delete( p ); > boost::throw_exception( std::bad_alloc() ); > } > > #endif > } > > > shared_count(shared_count && r): pi_(r.pi_) // nothrow > #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) > , id_(shared_count_id) > #endif > { > r.pi_ = 0; > } > > ~shared_count() // nothrow > { > if( pi_ != 0 ) pi_->release(); > #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) > id_ = 0; > #endif > } > > }; > > template< class T > struct sp_element > { > typedef T type; > }; > > template< class X, class Y, class T > inline void > sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, > boost::enable_shared_from_this< T > const * pe ) > { > if( pe != 0 ) > { > pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); > } > } > > struct sp_any_pointer > { > template<class T> sp_any_pointer( T* ) {} > }; > > inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, > sp_any_pointer ) > { > } > > template< class T, class Y > inline void sp_pointer_construct( > boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn ) > { > boost::detail::shared_count( p ).swap( pn ); > boost::detail::sp_enable_shared_from_this( ppx, p, p ); > } > > template< class T > struct sp_dereference > { > typedef T & type; > }; > > }//namespace detail > > template<class T> class shared_ptr > { > private: > > // Borland 5.5.1 specific workaround > typedef shared_ptr<T> this_type; > > public: > > typedef typename boost::detail::sp_element< T >::type element_type; > > template<class Y> > explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete > { > boost::detail::sp_pointer_construct( this, p, pn ); > } > > element_type * px; // contained pointer > boost::detail::shared_count pn; // reference counter > > typename boost::detail::sp_dereference< T >::type operator* () const > { > return *px; > } > > }; > > } // namespace boost > > extern "C" { > double test(void) { > boost::shared_ptr<int> y = boost::shared_ptr<int>(new int(42)); > return *y; > } > } > > int main(void){ > double result = test(); > cout<<result<<endl; > return 0; > } > > -- > You received this message because you are subscribed to the Google Groups > "emscripten-discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
