diff --git a/sp_debug_hooks.cpp b/sp_debug_hooks.cpp new file mode 100644 index 0000000..741ea3a --- /dev/null +++ b/sp_debug_hooks.cpp @@ -0,0 +1,228 @@ +// +// sp_debug_hooks.cpp +// +// Copyright (c) 2002 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. +// +// http://www.boost.org/libs/smart_ptr/debug_hooks.html +// + +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + +#include +#include +#include + +int const m = 2; // m * sizeof(int) must be aligned appropriately + +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 + +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 + +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_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; +} + +// 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 + +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_ENABLE_SP_DEBUG_HOOKS)