📄 object.cxx
字号:
object = ptr.object; if (object != NULL) ++object->referenceCount;}PSmartPointer & PSmartPointer::operator=(const PSmartPointer & ptr){ if (object == ptr.object) return *this; if ((object != NULL) && (--object->referenceCount == 0)) delete object; object = ptr.object; if (object != NULL) ++object->referenceCount; return *this;}PSmartPointer::~PSmartPointer(){ if ((object != NULL) && (--object->referenceCount == 0)) delete object;}PObject::Comparison PSmartPointer::Compare(const PObject & obj) const{ PAssert(PIsDescendant(&obj, PSmartPointer), PInvalidCast); PSmartObject * other = ((const PSmartPointer &)obj).object; if (object == other) return EqualTo; return object < other ? LessThan : GreaterThan;}//////////////////////////////////////////////////////////////////////////////////////////#if PMEMORY_CHECK#undef malloc#undef realloc#undef free#if (__GNUC__ >= 3) || ((__GNUC__ == 2)&&(__GNUC_MINOR__ >= 95)) //2.95.X & 3.Xvoid * operator new(size_t nSize) throw (std::bad_alloc)#elsevoid * operator new(size_t nSize)#endif{ return PMemoryHeap::Allocate(nSize, (const char *)NULL, 0, NULL);}#if (__GNUC__ >= 3) || ((__GNUC__ == 2)&&(__GNUC_MINOR__ >= 95)) //2.95.X & 3.Xvoid * operator new[](size_t nSize) throw (std::bad_alloc)#elsevoid * operator new[](size_t nSize)#endif{ return PMemoryHeap::Allocate(nSize, (const char *)NULL, 0, NULL);}#if (__GNUC__ >= 3) || ((__GNUC__ == 2)&&(__GNUC_MINOR__ >= 95)) //2.95.X & 3.Xvoid operator delete(void * ptr) throw()#elsevoid operator delete(void * ptr)#endif{ PMemoryHeap::Deallocate(ptr, NULL);}#if (__GNUC__ >= 3) || ((__GNUC__ == 2)&&(__GNUC_MINOR__ >= 95)) //2.95.X & 3.Xvoid operator delete[](void * ptr) throw()#elsevoid operator delete[](void * ptr)#endif{ PMemoryHeap::Deallocate(ptr, NULL);}DWORD PMemoryHeap::allocationBreakpoint = 0;char PMemoryHeap::Header::GuardBytes[NumGuardBytes];PMemoryHeap::Wrapper::Wrapper(){ // The following is done like this to get over brain dead compilers that cannot // guarentee that a static global is contructed before it is used. static PMemoryHeap real_instance; instance = &real_instance; if (instance->isDestroyed) return;#if defined(_WIN32) EnterCriticalSection(&instance->mutex);#elif defined(P_MAC_MPTHREADS) long err; PAssertOS((err = MPEnterCriticalRegion(instance->mutex, kDurationForever)) == 0);#elif defined(P_PTHREADS) pthread_mutex_lock(&instance->mutex);#elif defined(P_VXWORKS) semTake((SEM_ID)instance->mutex, WAIT_FOREVER);#endif}PMemoryHeap::Wrapper::~Wrapper(){ if (instance->isDestroyed) return;#if defined(_WIN32) LeaveCriticalSection(&instance->mutex);#elif defined(P_MAC_MPTHREADS) long err; PAssertOS((err = MPExitCriticalRegion(instance->mutex)) == 0 || instance->isDestroyed);#elif defined(P_PTHREADS) pthread_mutex_unlock(&instance->mutex);#elif defined(P_VXWORKS) semGive((SEM_ID)instance->mutex);#endif}PMemoryHeap::PMemoryHeap(){ isDestroyed = FALSE; listHead = NULL; listTail = NULL; allocationRequest = 1; firstRealObject = 0; flags = NoLeakPrint; allocFillChar = '\x5A'; freeFillChar = '\xA5'; currentMemoryUsage = 0; peakMemoryUsage = 0; currentObjects = 0; peakObjects = 0; totalObjects = 0; for (PINDEX i = 0; i < Header::NumGuardBytes; i++) Header::GuardBytes[i] = (i&1) == 0 ? '\x55' : '\xaa';#if defined(_WIN32) InitializeCriticalSection(&mutex); static PDebugStream debug; leakDumpStream = &debug;#else#if defined(P_PTHREADS) pthread_mutex_init(&mutex, NULL);#elif defined(P_VXWORKS) mutex = semMCreate(SEM_Q_FIFO);#endif leakDumpStream = &cerr;#endif}PMemoryHeap::~PMemoryHeap(){ if (leakDumpStream != NULL) { InternalDumpStatistics(*leakDumpStream); InternalDumpObjectsSince(firstRealObject, *leakDumpStream); } isDestroyed = TRUE;#if defined(_WIN32) DeleteCriticalSection(&mutex); extern void PWaitOnExitConsoleWindow(); PWaitOnExitConsoleWindow();#elif defined(P_PTHREADS) pthread_mutex_destroy(&mutex);#elif defined(P_VXWORKS) semDelete((SEM_ID)mutex);#endif}void * PMemoryHeap::Allocate(size_t nSize, const char * file, int line, const char * className){ Wrapper mem; return mem->InternalAllocate(nSize, file, line, className);}void * PMemoryHeap::Allocate(size_t count, size_t size, const char * file, int line){ Wrapper mem; char oldFill = mem->allocFillChar; mem->allocFillChar = '\0'; void * data = mem->InternalAllocate(count*size, file, line, NULL); mem->allocFillChar = oldFill; return data;}void * PMemoryHeap::InternalAllocate(size_t nSize, const char * file, int line, const char * className){ if (isDestroyed) return malloc(nSize); Header * obj = (Header *)malloc(sizeof(Header) + nSize + sizeof(Header::GuardBytes)); if (obj == NULL) { PAssertAlways(POutOfMemory); return NULL; } // Ignore all allocations made before main() is called. This is indicated // by PProcess::PreInitialise() clearing the NoLeakPrint flag. Why do we do // this? because the GNU compiler is broken in the way it does static global // C++ object construction and destruction. if (firstRealObject == 0 && (flags&NoLeakPrint) == 0) firstRealObject = allocationRequest; if (allocationBreakpoint != 0 && allocationRequest == allocationBreakpoint) {#ifdef _WIN32 __asm int 3;#elif defined(P_VXWORKS) kill(taskIdSelf(), SIGABRT);#else kill(getpid(), SIGABRT);#endif } currentMemoryUsage += nSize; if (currentMemoryUsage > peakMemoryUsage) peakMemoryUsage = currentMemoryUsage; currentObjects++; if (currentObjects > peakObjects) peakObjects = currentObjects; totalObjects++; char * data = (char *)&obj[1]; obj->prev = listTail; obj->next = NULL; obj->size = nSize; obj->fileName = file; obj->line = (WORD)line; obj->className = className; obj->request = allocationRequest++; obj->flags = flags; memcpy(obj->guard, obj->GuardBytes, sizeof(obj->guard)); memset(data, allocFillChar, nSize); memcpy(&data[nSize], obj->GuardBytes, sizeof(obj->guard)); if (listTail != NULL) listTail->next = obj; listTail = obj; if (listHead == NULL) listHead = obj; return data;}void * PMemoryHeap::Reallocate(void * ptr, size_t nSize, const char * file, int line){ if (ptr == NULL) return Allocate(nSize, file, line, NULL); if (nSize == 0) { Deallocate(ptr, NULL); return NULL; } Wrapper mem; if (mem->isDestroyed) return realloc(ptr, nSize); if (mem->InternalValidate(ptr, NULL, mem->leakDumpStream) != Ok) return NULL; Header * obj = (Header *)realloc(((Header *)ptr)-1, sizeof(Header) + nSize + sizeof(obj->guard)); if (obj == NULL) { PAssertAlways(POutOfMemory); return NULL; } if (mem->allocationBreakpoint != 0 && mem->allocationRequest == mem->allocationBreakpoint) {#ifdef _WIN32 __asm int 3;#elif defined(P_VXWORKS) kill(taskIdSelf(), SIGABRT);#else kill(getpid(), SIGABRT);#endif } mem->currentMemoryUsage -= obj->size; mem->currentMemoryUsage += nSize; if (mem->currentMemoryUsage > mem->peakMemoryUsage) mem->peakMemoryUsage = mem->currentMemoryUsage; char * data = (char *)&obj[1]; memcpy(&data[nSize], obj->GuardBytes, sizeof(obj->guard)); obj->size = nSize; obj->fileName = file; obj->line = (WORD)line; obj->request = mem->allocationRequest++; if (obj->prev != NULL) obj->prev->next = obj; else mem->listHead = obj; if (obj->next != NULL) obj->next->prev = obj; else mem->listTail = obj; return data;}void PMemoryHeap::Deallocate(void * ptr, const char * className){ if (ptr == NULL) return; Wrapper mem; Header * obj = ((Header *)ptr)-1; if (mem->isDestroyed) { free(obj); return; } switch (mem->InternalValidate(ptr, className, mem->leakDumpStream)) { case Ok : break; case Trashed : free(ptr); return; case Bad : free(obj); return; } if (obj->prev != NULL) obj->prev->next = obj->next; else mem->listHead = obj->next; if (obj->next != NULL) obj->next->prev = obj->prev; else mem->listTail = obj->prev; mem->currentMemoryUsage -= obj->size; mem->currentObjects--; memset(ptr, mem->freeFillChar, obj->size); // Make use of freed data noticable free(obj);}PMemoryHeap::Validation PMemoryHeap::Validate(void * ptr, const char * className, ostream * error){ Wrapper mem; return mem->InternalValidate(ptr, className, error);}PMemoryHeap::Validation PMemoryHeap::InternalValidate(void * ptr, const char * className, ostream * error){ if (isDestroyed) return Bad; if (ptr == NULL) return Trashed; Header * obj = ((Header *)ptr)-1; Header * link = listTail; while (link != NULL && link != obj) link = link->prev; if (link == NULL) { if (error != NULL) *error << "Block " << ptr << " not in heap!" << endl; return Trashed; } if (memcmp(obj->guard, obj->GuardBytes, sizeof(obj->guard)) != 0) { if (error != NULL) *error << "Underrun at " << ptr << '[' << obj->size << "] #" << obj->request << endl; return Bad; } if (memcmp((char *)ptr+obj->size, obj->GuardBytes, sizeof(obj->guard)) != 0) { if (error != NULL) *error << "Overrun at " << ptr << '[' << obj->size << "] #" << obj->request << endl; return Bad; } if (!(className == NULL && obj->className == NULL) && (className == NULL || obj->className == NULL || (className != obj->className && strcmp(obj->className, className) != 0))) { if (error != NULL) *error << "PObject " << ptr << '[' << obj->size << "] #" << obj->request << " allocated as \"" << (obj->className != NULL ? obj->className : "<NULL>") << "\" and should be \"" << (className != NULL ? className : "<NULL>") << "\"." << endl; return Bad; } return Ok;}BOOL PMemoryHeap::ValidateHeap(ostream * error){ Wrapper mem; if (error == NULL) error = mem->leakDumpStream; Header * obj = mem->listHead; while (obj != NULL) { if (memcmp(obj->guard, obj->GuardBytes, sizeof(obj->guard)) != 0) { if (error != NULL) *error << "Underrun at " << (obj+1) << '[' << obj->size << "] #" << obj->request << endl; return FALSE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -