// // sp_debug_hooks.cpp // // Copyright (c) 2002, 2003 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #include #include #include int const m = 2; // m * sizeof(int) must be aligned appropriately // magic values to mark heap blocks with int const allocated_scalar = 0x1234560C; int const allocated_array = 0x1234560A; int const adopted_scalar = 0x0567890C; int const adopted_array = 0x0567890A; int const deleted = 0x498769DE; using namespace std; // for compilers where things aren't in std // operator new static new_handler get_new_handler() { new_handler p = set_new_handler(0); set_new_handler(p); return p; } static void * allocate(size_t n, int mark) { int * pm; for(;;) { pm = static_cast(malloc(n + m * sizeof(int))); if(pm != 0) break; if(new_handler pnh = get_new_handler()) { pnh(); } else { return 0; } } *pm = mark; return pm + m; } void * operator new(size_t n) throw(bad_alloc) { void * p = allocate(n, allocated_scalar); #if !defined(BOOST_NO_EXCEPTIONS) if(p == 0) throw bad_alloc(); #endif return p; } #if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) void * operator new(size_t n, nothrow_t const &) throw() { return allocate(n, allocated_scalar); } #endif void * operator new[](size_t n) throw(bad_alloc) { void * p = allocate(n, allocated_array); #if !defined(BOOST_NO_EXCEPTIONS) if(p == 0) throw bad_alloc(); #endif return p; } #if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) void * operator new[](size_t n, nothrow_t const &) throw() { return allocate(n, allocated_array); } #endif // debug hooks namespace boost { void sp_scalar_constructor_hook(void * p) { if(p == 0) return; int * pm = static_cast(p); pm -= m; BOOST_ASSERT(*pm != adopted_scalar); // second smart pointer to the same address BOOST_ASSERT(*pm != allocated_array); // allocated with new[] BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new *pm = adopted_scalar; } void sp_scalar_constructor_hook(void * px, std::size_t, void *) { sp_scalar_constructor_hook(px); } void sp_scalar_destructor_hook(void * p) { if(p == 0) return; int * pm = static_cast(p); pm -= m; BOOST_ASSERT(*pm == adopted_scalar); // attempt to destroy nonmanaged block *pm = allocated_scalar; } void sp_scalar_destructor_hook(void * px, std::size_t, void *) { sp_scalar_destructor_hook(px); } // It is not possible to handle the array hooks in a portable manner. // The implementation typically reserves a bit of storage for the number // of objects in the array, and the argument of the array hook isn't // equal to the return value of operator new[]. void sp_array_constructor_hook(void * /* p */) { /* if(p == 0) return; // adjust p depending on the implementation int * pm = static_cast(p); pm -= m; BOOST_ASSERT(*pm != adopted_array); // second smart array pointer to the same address BOOST_ASSERT(*pm != allocated_scalar); // allocated with new BOOST_ASSERT(*pm == allocated_array); // not allocated with new[] *pm = adopted_array; */ } void sp_array_destructor_hook(void * /* p */) { /* if(p == 0) return; // adjust p depending on the implementation int * pm = static_cast(p); pm -= m; BOOST_ASSERT(*pm == adopted_array); // attempt to destroy nonmanaged block *pm = allocated_array; */ } } // namespace boost // operator delete void operator delete(void * p) throw() { if(p == 0) return; int * pm = static_cast(p); pm -= m; BOOST_ASSERT(*pm != deleted); // double delete BOOST_ASSERT(*pm != adopted_scalar); // delete p.get(); BOOST_ASSERT(*pm != allocated_array); // allocated with new[] BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new *pm = deleted; free(pm); } #if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) void operator delete(void * p, nothrow_t const &) throw() { ::operator delete(p); } #endif void operator delete[](void * p) throw() { if(p == 0) return; int * pm = static_cast(p); pm -= m; BOOST_ASSERT(*pm != deleted); // double delete BOOST_ASSERT(*pm != adopted_scalar); // delete p.get(); BOOST_ASSERT(*pm != allocated_scalar); // allocated with new BOOST_ASSERT(*pm == allocated_array); // not allocated with new[] *pm = deleted; free(pm); } #if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) void operator delete[](void * p, nothrow_t const &) throw() { ::operator delete[](p); } #endif #endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)