📄 ncbiobj.cpp
字号:
"CObject is corrupted");}static bool s_EnvFlag(const char* env_var_name){ const char* value = getenv(env_var_name); return value && (*value == 'Y' || *value == 'y' || *value == '1');} void CObjectException::x_InitErrCode(CException::EErrCode err_code){ CCoreException::x_InitErrCode(err_code); static bool abort_on_throw = s_EnvFlag("NCBI_ABORT_ON_COBJECT_THROW"); if ( abort_on_throw ) { Abort(); }}void CObject::DebugDump(CDebugDumpContext ddc, unsigned int /*depth*/) const{ ddc.SetFrame("CObject"); ddc.Log("address", dynamic_cast<const CDebugDumpable*>(this), 0);// ddc.Log("memory starts at", dynamic_cast<const void*>(this));// ddc.Log("onHeap", CanBeDeleted());}void CObject::ThrowNullPointerException(void){ static bool abort_on_null = s_EnvFlag("NCBI_ABORT_ON_NULL"); if ( abort_on_null ) { Abort(); } NCBI_THROW(CCoreException, eNullPtr, "Attempt to access NULL pointer.");}END_NCBI_SCOPE#if 0struct SAllocHeader{ unsigned magic; unsigned seq_number; size_t size; void* ptr;};struct SAllocFooter{ void* ptr; size_t size; unsigned seq_number; unsigned magic;};static const size_t kAllocSizeBefore = sizeof(SAllocHeader)+8;static const size_t kAllocSizeAfter = sizeof(SAllocFooter)+8;static const char kAllocFillBefore1 = 0xaa;static const char kAllocFillBefore2 = 0xbb;static const char kAllocFillInside = 0xcc;static const char kAllocFillAfter = 0xdd;static const char kAllocFillFree = 0xee;static const unsigned kAllocMagicHeader = 0x89abcdef;static const unsigned kAllocMagicFooter = 0xfedcba98;static std::bad_alloc bad_alloc_instance;DEFINE_STATIC_FAST_MUTEX(s_alloc_mutex);static NCBI_NS_NCBI::CAtomicCounter seq_number;static const size_t kLogSize = 64 * 1024;struct SAllocLog { unsigned seq_number; enum EType { eEmpty = 0, eInit, eNew, eNewArr, eDelete, eDeleteArr }; char type; char completed; size_t size; void* ptr;};static SAllocLog alloc_log[kLogSize];static inline SAllocHeader* get_header(void* ptr){ return (SAllocHeader*) ((char*) ptr-kAllocSizeBefore);}static inline void* get_guard_before(SAllocHeader* header){ return (char*) header + sizeof(SAllocHeader);}static inline size_t get_guard_before_size(){ return kAllocSizeBefore - sizeof(SAllocHeader);}static inline size_t get_extra_size(size_t size){ return (-size) & 7;}static inline size_t get_guard_after_size(size_t size){ return kAllocSizeAfter - sizeof(SAllocFooter) + get_extra_size(size);}static inline void* get_ptr(SAllocHeader* header){ return (char*) header + kAllocSizeBefore;}static inline void* get_guard_after(SAllocFooter* footer, size_t size){ return (char*)footer-get_guard_after_size(size);}static inline SAllocFooter* get_footer(SAllocHeader* header, size_t size){ return (SAllocFooter*)((char*)get_ptr(header)+size+get_guard_after_size(size));}static inline size_t get_total_size(size_t size){ return size+get_extra_size(size) + (kAllocSizeBefore+kAllocSizeAfter);}static inline SAllocLog& start_log(unsigned number, SAllocLog::EType type){ SAllocLog& slot = alloc_log[number % kLogSize]; slot.type = SAllocLog::eInit; slot.completed = false; slot.seq_number = number; slot.ptr = 0; slot.size = 0; slot.type = type; return slot;}static inlinevoid memchk(const void* ptr, char byte, size_t size){ for ( const char* mem = (const char*)ptr; size && *mem == byte; ++mem, --size ) { } if ( size ) { std::abort(); }}static inlinevoid* alloc_mem(size_t size, bool array) throw(){ unsigned number = seq_number.Add(1); SAllocLog& log = start_log(number, array? SAllocLog::eNewArr: SAllocLog::eNew); log.size = size; SAllocHeader* header; {{ NCBI_NS_NCBI::CFastMutexGuard guard(s_alloc_mutex); header = (SAllocHeader*)std::malloc(get_total_size(size)); }} if ( !header ) { log.completed = true; return 0; } SAllocFooter* footer = get_footer(header, size); header->magic = kAllocMagicHeader; footer->magic = kAllocMagicFooter; header->seq_number = footer->seq_number = number; header->size = footer->size = size; header->ptr = footer->ptr = log.ptr = get_ptr(header); std::memset(get_guard_before(header), array? kAllocFillBefore2: kAllocFillBefore1, get_guard_before_size()); std::memset(get_guard_after(footer, size), kAllocFillAfter, get_guard_after_size(size)); std::memset(get_ptr(header), kAllocFillInside, size); log.completed = true; return get_ptr(header);}static inlinevoid free_mem(void* ptr, bool array){ unsigned number = seq_number.Add(1); SAllocLog& log = start_log(number, array ? SAllocLog::eDeleteArr: SAllocLog::eDelete); if ( ptr ) { log.ptr = ptr; SAllocHeader* header = get_header(ptr); if ( header->magic != kAllocMagicHeader || header->seq_number >= number || header->ptr != get_ptr(header) ) { abort(); } size_t size = log.size = header->size; SAllocFooter* footer = get_footer(header, size); if ( footer->magic != kAllocMagicFooter || footer->seq_number != header->seq_number || footer->ptr != get_ptr(header) || footer->size != size ) { abort(); } memchk(get_guard_before(header), array? kAllocFillBefore2: kAllocFillBefore1, get_guard_before_size()); memchk(get_guard_after(footer, size), kAllocFillAfter, get_guard_after_size(size)); std::memset(header, kAllocFillFree, get_total_size(size)); {{ NCBI_NS_NCBI::CFastMutexGuard guard(s_alloc_mutex); std::free(header); }} } log.completed = true;}void* operator new(size_t size) throw(std::bad_alloc){ void* ret = alloc_mem(size, false); if ( !ret ) throw bad_alloc_instance; return ret;}void* operator new(size_t size, const std::nothrow_t&) throw(){ return alloc_mem(size, false);}void* operator new[](size_t size) throw(std::bad_alloc){ void* ret = alloc_mem(size, true); if ( !ret ) throw bad_alloc_instance; return ret;}void* operator new[](size_t size, const std::nothrow_t&) throw(){ return alloc_mem(size, true);}void operator delete(void* ptr) throw(){ free_mem(ptr, false);}void operator delete(void* ptr, const std::nothrow_t&) throw(){ free_mem(ptr, false);}void operator delete[](void* ptr) throw(){ free_mem(ptr, true);}void operator delete[](void* ptr, const std::nothrow_t&) throw(){ free_mem(ptr, true);}#endif/* * =========================================================================== * $Log: ncbiobj.cpp,v $ * Revision 1000.5 2004/06/01 19:09:16 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45 * * Revision 1.45 2004/05/14 13:59:27 gorelenk * Added include of ncbi_pch.hpp * * Revision 1.44 2004/04/05 15:58:43 vakatov * CObject::InitCounter() -- ATTENTION: this code can cause UMR -- it's okay * * Revision 1.43 2004/02/19 16:44:19 vasilche * Modified debug new/delete code for 64 bit builds. * * Revision 1.42 2004/02/17 21:08:19 vasilche * Added code to debug memory allocation problems (currently commented out). * * Revision 1.41 2003/12/17 20:10:07 vasilche * Avoid throwing exceptions from destructors. * Display Fatal message in Debug mode and Critical message in Release mode. * * Revision 1.40 2003/09/17 15:58:29 vasilche * Allow debug abort when: * CObjectException is thrown - env var NCBI_ABORT_ON_COBJECT_THROW=[Yy1], * CNullPointerException is thrown - env var NCBI_ABORT_ON_NULL=[Yy1]. * Allow quit abort in debug mode and coredump in release mode: * env var DIAG_SILENT_ABORT=[Yy1Nn0]. * * Revision 1.39 2003/09/17 15:20:46 vasilche * Moved atomic counter swap functions to separate file. * Added CRef<>::AtomicResetFrom(), CRef<>::AtomicReleaseTo() methods. * * Revision 1.38 2003/08/12 12:06:58 siyan * Changed name of implementation for AddReferenceOverflow(). It is now * CheckReferenceOverflow(). * * Revision 1.37 2003/07/17 23:01:32 vasilche * Added matching operator delete. * * Revision 1.36 2003/07/17 20:01:07 vasilche * Added inplace operator new(). * * Revision 1.35 2003/03/06 19:40:52 ucko * InitCounter: read m_Value directly rather than going through Get(), which * would end up spinning forever if it came across NCBI_COUNTER_RESERVED_VALUE. * * Revision 1.34 2002/11/27 12:53:45 dicuccio * Added CObject::ThrowNullPointerException() to get around some inlining issues. * * Revision 1.33 2002/09/20 13:52:46 vasilche * Renamed sm_Mutex -> sm_AtomicCounterMutex * * Revision 1.32 2002/09/19 20:05:43 vasilche * Safe initialization of static mutexes * * Revision 1.31 2002/08/28 17:05:50 vasilche * Remove virtual inheritance, fixed heap detection * * Revision 1.30 2002/07/15 18:17:24 gouriano * renamed CNcbiException and its descendents * * Revision 1.29 2002/07/11 14:18:27 gouriano * exceptions replaced by CNcbiException-type ones * * Revision 1.28 2002/05/29 21:17:57 gouriano * minor change in debug dump * * Revision 1.27 2002/05/28 17:59:55 gouriano * minor modification od DebugDump * * Revision 1.26 2002/05/24 14:12:10 ucko * Provide CAtomicCounter::sm_Mutex if necessary. * * Revision 1.25 2002/05/23 22:24:23 ucko * Use low-level atomic operations for reference counts * * Revision 1.24 2002/05/17 14:27:12 gouriano * added DebugDump base class and function to CObject * * Revision 1.23 2002/05/14 21:12:11 gouriano * DebugDump() moved into a separate class * * Revision 1.22 2002/05/14 14:44:24 gouriano * added DebugDump function to CObject * * Revision 1.21 2002/05/10 20:53:12 gouriano * more stack/heap tests * * Revision 1.20 2002/05/10 19:42:31 gouriano * object on stack vs on heap - do it more accurately * * Revision 1.19 2002/04/11 21:08:03 ivanov * CVS log moved to end of the file * * Revision 1.18 2001/08/20 18:35:10 ucko * Clarified InitCounter's treatment of statically allocated objects. * * Revision 1.17 2001/08/20 15:59:43 ucko * Test more accurately whether CObjects were created on the stack. * * Revision 1.16 2001/05/17 15:04:59 lavr * Typos corrected * * Revision 1.15 2001/04/03 18:08:54 grichenk * Converted eCounterNotInHeap to TCounter(eCounterNotInHeap) * * Revision 1.14 2001/03/26 21:22:52 vakatov * Minor cosmetics * * Revision 1.13 2001/03/13 22:43:50 vakatov * Made "CObject" MT-safe * + CObject::DoDeleteThisObject() * * Revision 1.12 2000/12/26 22:00:19 vasilche * Fixed error check for case CObject constructor never called. * * Revision 1.11 2000/11/01 21:20:55 vasilche * Fixed missing new[] and delete[] on MSVC. * * Revision 1.10 2000/11/01 20:37:16 vasilche * Fixed detection of heap objects. * Removed ECanDelete enum and related constructors. * Disabled sync_with_stdio ad the beginning of AppMain. * * Revision 1.9 2000/10/17 17:59:08 vasilche * Detected misuse of CObject constructors will be reported via ERR_POST * and will not throw exception. * * Revision 1.8 2000/10/13 16:26:30 vasilche * Added heuristic for detection of CObject allocation in heap. * * Revision 1.7 2000/08/15 19:41:41 vasilche * Changed reference counter to allow detection of more errors. * * Revision 1.6 2000/06/16 16:29:51 vasilche * Added SetCanDelete() method to allow to change CObject 'in heap' status * immediately after creation. * * Revision 1.5 2000/06/07 19:44:22 vasilche * Removed unneeded THROWS declaration - they lead to encreased code size. * * Revision 1.4 2000/03/29 15:50:41 vasilche * Added const version of CRef - CConstRef. * CRef and CConstRef now accept classes inherited from CObject. * * Revision 1.3 2000/03/08 17:47:30 vasilche * Simplified error check. * * Revision 1.2 2000/03/08 14:18:22 vasilche * Fixed throws instructions. * * Revision 1.1 2000/03/07 14:03:15 vasilche * Added CObject class as base for reference counted objects. * Added CRef templace for reference to CObject descendant. * * =========================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -