#ifndef _DEBUG_PTR_H_ #define _DEBUG_PTR_H_ // Intended to be include only in "debug_allocator.h" #ifdef DEBUG_ALLOC #include // A minimal raw pointer wrapper to support heap pointer tracking along with // DebugAllocator. template class DebugPtr { public: DebugPtr() : p_(NULL), age_(0) {} DebugPtr(T* p) : p_(p) { age_ = DebugAllocator::RetrieveAge(p_); } template DebugPtr(U* p) : p_(static_cast(p)) { age_ = DebugAllocator::RetrieveAge(p_); } DebugPtr(T* p, size_t age) : p_(p), age_(age) {} DebugPtr(const DebugPtr& o) : p_(o.p_), age_(o.age_) {} template DebugPtr(const DebugPtr& o) : p_(static_cast(o.Get())), age_(o.GetAge()) {} ~DebugPtr() {} T& operator*() const { return *(GetVerified()); } T* operator->() const { return GetVerified(); } // Gets the underlying heap pointer. T* Get() const { return p_; } // Gets the age of the underlying heap pointer. size_t GetAge() const { return age_; } // Assignment operator for DebugPtr DebugPtr& operator=(const DebugPtr& rhs) { DebugPtr ptr(rhs); return Swap(ptr); } // Assignment operator for DebugPtr template DebugPtr& operator=(const DebugPtr& rhs) { DebugPtr ptr(rhs); return Swap(ptr); } // Conversion operator operator T*() const { return GetVerified(); } bool operator!() const { return (Get() == NULL); } private: T* GetVerified() const { T* p = p_; if (p != NULL) { // Quick test first size_t age = *(reinterpret_cast(p) - 1); if (age != age_) { if (DebugAllocator::Verify(p, age_) != NULL) { // Age header corrupted DebugAllocator::LogBoundaryCorruption(p, age); } // Make it crash immediately int* no_way = NULL; *no_way = 0; //p = NULL; } } return p; } DebugPtr& Swap(DebugPtr& o) { std::swap(p_, o.p_); std::swap(age_, o.age_); return *this; } T* p_; size_t age_; }; template inline bool operator==(const DebugPtr& a, const DebugPtr& b) { return a.Get() == b.Get(); } template inline bool operator!=(const DebugPtr& a, const DebugPtr& b) { return a.Get() != b.Get(); } template inline bool operator==(const DebugPtr& a, U* b) { return a.Get() == b; } template inline bool operator!=(const DebugPtr& a, U* b) { return a.Get() != b; } template inline bool operator==(T* a, const DebugPtr& b) { return a == b.Get(); } template inline bool operator!=(T* a, const DebugPtr& b) { return a != b.Get(); } template inline DebugPtr static_pointer_cast(const DebugPtr& o) { return DebugPtr(static_cast(o.Get()), o.GetAge()); } template inline DebugPtr const_pointer_cast(const DebugPtr& o) { return DebugPtr(const_cast(o.Get()), o.GetAge()); } template inline DebugPtr dynamic_pointer_cast(const DebugPtr& o) { return DebugPtr(dynamic_cast(o.Get()), o.GetAge()); } template T* get_pointer(DebugPtr& ptr) { return ptr.Get(); } namespace std { template struct less > { bool operator()(const DebugPtr& lhs, const DebugPtr& rhs) const { return (reinterpret_cast(lhs.Get()) < reinterpret_cast(rhs.Get())); } }; template struct equal_to > { bool operator()(const DebugPtr& lhs, const DebugPtr& rhs) const { return (lhs.Get() == rhs.Get()); } }; template bool operator<(const DebugPtr& lhs, const DebugPtr& rhs) { return (reinterpret_cast(lhs.Get()) < reinterpret_cast(rhs.Get())); } } // namespace std #ifdef __GNUC__ namespace std { namespace tr1 { #else namespace boost { #endif template struct hash > { size_t operator()(const DebugPtr& v) const { return reinterpret_cast(v.Get()); } }; #ifdef __GNUC__ }} // namespace std::tr1 #else } // namespace boost #endif #endif // DEBUG_ALLOC #endif // _DEBUG_PTR_H_