📄 object.h
字号:
The #ptr# parameter is validated as a currently allocated heap variable. @return Ok for pointer is in heap, Bad for pointer is not in the heap or Trashed if the pointer is in the heap but has overwritten the guard bytes before or after the actual data part of the memory block. */ static Validation Validate( void * ptr, /// Pointer to memory block to check const char * className, /// Class name it should be. ostream * error /// Stream to receive error message (may be NULL) ); /** Validate all objects in memory. This effectively calls Validate() on every object in the heap. @return TRUE if every object in heap is Ok. */ static BOOL ValidateHeap( ostream * error = NULL // Stream to output, use default if NULL ); /** Ignore/Monitor allocations. Set internal flag so that allocations are not included in the memory leak check on program termination. Returns the previous state. */ static BOOL SetIgnoreAllocations( BOOL ignore /// New flag for allocation ignoring. ); /** Get memory check system statistics. Dump statistics output to the default stream. */ static void DumpStatistics(); /** Get memory check system statistics. Dump statistics output to the specified stream. */ static void DumpStatistics(ostream & strm /** Stream to output to */); /* Get number of allocation. Each allocation is counted and if desired the next allocation request number may be obtained via this function. @return Allocation request number. */ static DWORD GetAllocationRequest(); /** Dump allocated objects. Dump ojects allocated and not deallocated since the specified object number. This would be a value returned by the #GetAllocationRequest()# function. Output is to the default stream. */ static void DumpObjectsSince( DWORD objectNumber /// Memory object to begin dump from. ); /** Dump allocated objects. Dump ojects allocated and not deallocated since the specified object number. This would be a value returned by the #GetAllocationRequest()# function. */ static void DumpObjectsSince( DWORD objectNumber, /// Memory object to begin dump from. ostream & strm /// Stream to output dump ); /** Set break point allocation number. Set the allocation request number to cause an assert. This allows a developer to cause a halt in a debugger on a certain allocation allowing them to determine memory leaks allocation point. */ static void SetAllocationBreakpoint( DWORD point /// Allocation number to stop at. ); protected: void * InternalAllocate( size_t nSize, // Number of bytes to allocate. const char * file, // Source file name for allocating function. int line, // Source file line for allocating function. const char * className // Class name for allocating function. ); Validation InternalValidate( void * ptr, // Pointer to memory block to check const char * className, // Class name it should be. ostream * error // Stream to receive error message (may be NULL) ); void InternalDumpStatistics(ostream & strm); void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm); class Wrapper { public: Wrapper(); ~Wrapper(); PMemoryHeap * operator->() const { return instance; } private: PMemoryHeap * instance; }; friend class Wrapper; enum Flags { NoLeakPrint = 1 };#pragma pack(1) struct Header { enum { // Assure that the Header struct is aligned to 8 byte boundary NumGuardBytes = 16 - (sizeof(Header *) + sizeof(Header *) + sizeof(const char *) + sizeof(const char *) + sizeof(size_t) + sizeof(DWORD) + sizeof(WORD) + sizeof(BYTE))%8 }; Header * prev; Header * next; const char * className; const char * fileName; size_t size; DWORD request; WORD line; BYTE flags; char guard[NumGuardBytes]; static char GuardBytes[NumGuardBytes]; };#pragma pack() BOOL isDestroyed; Header * listHead; Header * listTail; static DWORD allocationBreakpoint; DWORD allocationRequest; DWORD firstRealObject; BYTE flags; char allocFillChar; char freeFillChar; DWORD currentMemoryUsage; DWORD peakMemoryUsage; DWORD currentObjects; DWORD peakObjects; DWORD totalObjects; ostream * leakDumpStream;#if defined(_WIN32) CRITICAL_SECTION mutex;#elif defined(P_PTHREADS) pthread_mutex_t mutex;#elif defined(P_VXWORKS) void * mutex;#endif};/** Allocate memory for the run time library.This version of free is used for data that is not to be allocated using thememory check system, ie will be free'ed inside the C run time library.*/inline void * runtime_malloc(size_t bytes /** Size of block to allocate */ ) { return malloc(bytes); }/** Free memory allocated by run time library.This version of free is used for data that is not allocated using thememory check system, ie was malloc'ed inside the C run time library.*/inline void runtime_free(void * ptr /** Memory block to free */ ) { free(ptr); }/** Override of system call for memory check system.This macro is used to allocate memory via the memory check system selectedwith the #PMEMORY_CHECK# compile time option. It will include the source fileand line into the memory allocation to allow the PMemoryHeap class to keeptrack of the memory block.*/#define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)/** Override of system call for memory check system.This macro is used to allocate memory via the memory check system selectedwith the #PMEMORY_CHECK# compile time option. It will include the source fileand line into the memory allocation to allow the PMemoryHeap class to keeptrack of the memory block.*/#define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)/** Override of system call for memory check system.This macro is used to allocate memory via the memory check system selectedwith the #PMEMORY_CHECK# compile time option. It will include the source fileand line into the memory allocation to allow the PMemoryHeap class to keeptrack of the memory block.*/#define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)/** Override of system call for memory check system.This macro is used to deallocate memory via the memory check system selectedwith the #PMEMORY_CHECK# compile time option. It will include the source fileand line into the memory allocation to allow the PMemoryHeap class to keeptrack of the memory block.*/#define free(p) PMemoryHeap::Deallocate(p, NULL)/** Override of system call for memory check system.This macro is used to deallocate memory via the memory check system selectedwith the #PMEMORY_CHECK# compile time option. It will include the source fileand line into the memory allocation to allow the PMemoryHeap class to keeptrack of the memory block.*/#define cfree(p) PMemoryHeap::Deallocate(p, NULL)/** Macro for overriding system default #new# operator.This macro is used to allocate memory via the memory check system selectedwith the PMEMORY_CHECK compile time option. It will include the source fileand line into the memory allocation to allow the PMemoryHeap class to keeptrack of the memory block.This macro could be used instead of the system #new# operator. Or you can placethe line\begin{verbatim} #define new PNEW\end{verbatim}at the begining of the source file, after all declarations that use thePCLASSINFO macro.*/#define PNEW new (__FILE__, __LINE__)#if !defined(_MSC_VER) || _MSC_VER<1200#define PSPECIAL_DELETE_FUNCTION#else#define PSPECIAL_DELETE_FUNCTION \ void operator delete(void * ptr, const char *, int) \ { PMemoryHeap::Deallocate(ptr, Class()); } \ void operator delete[](void * ptr, const char *, int) \ { PMemoryHeap::Deallocate(ptr, Class()); }#endif#define PNEW_AND_DELETE_FUNCTIONS \ void * operator new(size_t nSize, const char * file, int line) \ { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \ void * operator new(size_t nSize) \ { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \ void operator delete(void * ptr) \ { PMemoryHeap::Deallocate(ptr, Class()); } \ void * operator new[](size_t nSize, const char * file, int line) \ { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \ void * operator new[](size_t nSize) \ { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \ void operator delete[](void * ptr) \ { PMemoryHeap::Deallocate(ptr, Class()); } \ PSPECIAL_DELETE_FUNCTIONinline void * operator new(size_t nSize, const char * file, int line) { return PMemoryHeap::Allocate(nSize, file, line, NULL); }inline void * operator new[](size_t nSize, const char * file, int line) { return PMemoryHeap::Allocate(nSize, file, line, NULL); }#ifndef __GNUC__void * operator new(size_t nSize);void * operator new[](size_t nSize);void operator delete(void * ptr);void operator delete[](void * ptr);#if defined(_MSC_VER) && _MSC_VER>=1200inline void operator delete(void * ptr, const char *, int) { PMemoryHeap::Deallocate(ptr, NULL); }inline void operator delete[](void * ptr, const char *, int) { PMemoryHeap::Deallocate(ptr, NULL); }#endif#endif#else // PMEMORY_CHECK#define PNEW new#if defined(__GNUC__) || (defined(_WIN32_WCE) && defined(_X86_))#define PNEW_AND_DELETE_FUNCTIONS#else#define PNEW_AND_DELETE_FUNCTIONS \ void * operator new(size_t nSize) \ { return malloc(nSize); } \ void operator delete(void * ptr) \ { free(ptr); } \ void * operator new[](size_t nSize) \ { return malloc(nSize); } \ void operator delete[](void * ptr) \ { free(ptr); }void * operator new(size_t nSize);void * operator new[](size_t nSize);void operator delete(void * ptr);void operator delete[](void * ptr);#endif#define runtime_malloc(s) malloc(s)#define runtime_free(p) free(p)#endif // PMEMORY_CHECK/** Declare all the standard PWlib class information.This macro is used to provide the basic run-time typing capability neededby the library. All descendent classes from the #PObject# class requirethese functions for correct operation. Either use this macro or the#PDECLARE_CLASS# macro.The use of the #PDECLARE_CLASS# macro is no longer recommended for reasonsof compatibility with documentation systems.*//* ORIGINAL#define PCLASSINFO(cls, par) \ public: \ static const char * Class() \ { return #cls; } \ virtual const char * GetClass(unsigned ancestor = 0) const \ { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \ virtual BOOL IsClass(const char * clsName) const \ { return strcmp(clsName, cls::Class()) == 0; } \ virtual BOOL IsDescendant(const char * clsName) const \ { return strcmp(clsName, cls::Class()) == 0 || par::IsDescendant(clsName); } \ virtual Comparison CompareObjectMemoryDirect(const PObject & obj) const \ { return (Comparison)memcmp(this, &obj, sizeof(cls)); } */#if P_HAS_TYPEINFO#define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL) #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str)) #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))#if P_USE_ASSERTStemplate<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line) { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }#define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)#else#define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))#endif#include <typeinfo>#ifndef PCLASSNAME#error "Must define PCLASSNAME"#endif#define PBASECLASSINFO(cls, par) \ public: \ static inline const char * Class() \ { return PCLASSNAME(cls); } \ virtual BOOL InternalIsDescendant(const char * clsName) const \ { return strcmp(clsName, PCLASSNAME(cls)) == 0 || par::InternalIsDescendant(clsName); } \#else // P_HAS_TYPEINFO#define PIsDescendant(ptr, cls) ((ptr)->InternalIsDescendant(cls::Class()))#define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))#define PRemoveConst(cls, ptr) ((cls*)(ptr))#if P_USE_ASSERTStemplate<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line) { if (obj->InternalIsDescendant(BaseClass::Class()) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }#define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)#else#define PDownCast(cls, ptr) ((cls*)(ptr))#endif#define PBASECLASSINFO(cls, par) \ public: \ static const char * Class() \ { return #cls; } \ virtual BOOL InternalIsDescendant(const char * clsName) const \ { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \#endif // P_HAS_TYPEINFO#define PCLASSINFO(cls, par) \ PBASECLASSINFO(cls, par) \ virtual const char * GetClass(unsigned ancestor = 0) const \ { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \ virtual Comparison CompareObjectMemoryDirect(const PObject & obj) const \ { return (Comparison)memcmp(this, &obj, sizeof(cls)); } \/** Declare a class with PWLib class information.This macro is used to declare a new class with a single public ancestor. Itstarts the class declaration and then uses the #PCLASSINFO# macro toget all the run-time type functions.The use of this macro is no longer recommended for reasons of compatibilitywith documentation systems.*/#define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)#ifdef DOC_PLUS_PLUS} Match previous opening brace in doc++#endif///////////////////////////////////////////////////////////////////////////////// The root of all evil ... umm classes/** Ultimate parent class for all objects in the class library.This provides functionality provided to all classes, eg run-time types,default comparison operations, simple stream I/O and serialisation support.*/class PObject { protected: /** Constructor for PObject, make protected so cannot ever create one on its own. */ PObject() { } public: /* Destructor required to get the "virtual". A PObject really has nothing to destroy. */ virtual ~PObject() { } /**@name Run Time Type functions */ //@{ /** Get the name of the class as a C string. This is a static function which returns the type of a specific class. When comparing class names, always use the #strcmp()# function rather than comparing pointers. The pointers are not necessarily the same over compilation units depending on the compiler, platform etc. @return pointer to C string literal. */ static inline const char * Class() { return PCLASSNAME(PObject); } /** Get the current dynamic type of the object instance.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -