📄 object.cxx
字号:
/*
* object.cxx
*
* Global object support.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: object.cxx,v $
* Revision 1.42 1999/11/01 00:17:20 robertj
* Added override of new functions for MSVC memory check code.
*
* Revision 1.41 1999/08/22 13:38:39 robertj
* Fixed termination hang up problem with memory check code under unix pthreads.
*
* Revision 1.40 1999/08/10 10:45:09 robertj
* Added mutex in memory check detection code.
*
* Revision 1.39 1999/07/18 15:08:48 robertj
* Fixed 64 bit compatibility
*
* Revision 1.38 1999/05/01 11:29:20 robertj
* Alpha linux port changes.
*
* Revision 1.37 1999/03/09 10:30:17 robertj
* Fixed ability to have PMEMORY_CHECK on/off on both debug/release versions.
*
* Revision 1.36 1999/02/22 10:48:14 robertj
* Fixed delete operator prototypes for MSVC6 and GNU compatibility.
*
* Revision 1.35 1998/12/22 10:24:17 robertj
* Fixed MSVC warnings caused by changes made in linux PPC support.
*
* Revision 1.34 1998/12/15 09:01:10 robertj
* Fixed 8 byte alignment problem in memory leak check code for sparc.
*
* Revision 1.33 1998/11/30 05:33:00 robertj
* Fixed duplicate debug stream class, ther can be only one.
*
* Revision 1.32 1998/11/03 03:11:53 robertj
* Fixed memory leak question so correctly detects leaks and can be ^C'd.
*
* Revision 1.31 1998/11/03 00:55:31 robertj
* Added allocation breakpoint variable.
*
* Revision 1.30 1998/10/15 07:48:56 robertj
* Added hex dump to memory leak.
* Added ability to ignore G++lib memory leaks.
*
* Revision 1.29 1998/10/15 01:53:35 robertj
* GNU compatibility.
*
* Revision 1.28 1998/10/13 14:06:26 robertj
* Complete rewrite of memory leak detection code.
*
* Revision 1.27 1998/09/23 06:22:22 robertj
* Added open source copyright license.
*
* Revision 1.26 1998/05/30 13:27:02 robertj
* Changed memory check code so global statics are not included in leak check.
*
* Revision 1.25 1997/07/08 13:07:07 robertj
* DLL support.
*
* Revision 1.24 1997/02/09 03:45:28 robertj
* Fixed unix/dos compatibility with include file.
*
* Revision 1.23 1997/02/05 11:54:12 robertj
* Fixed problems with memory check and leak detection.
*
* Revision 1.22 1996/08/08 10:08:46 robertj
* Directory structure changes for common files.
*
* Revision 1.21 1996/07/15 10:35:11 robertj
* Changed memory leak dump to use static class rather than atexit for better portability.
*
* Revision 1.20 1996/06/17 11:35:47 robertj
* Fixed display of memory leak info, needed flush and use of cin as getchar() does not work with services.
*
* Revision 1.19 1996/05/09 12:19:29 robertj
* Fixed up 64 bit integer class for Mac platform.
* Fixed incorrect use of memcmp/strcmp return value.
*
* Revision 1.18 1996/03/26 00:55:20 robertj
* Added keypress before dumping memory leaks.
*
* Revision 1.17 1996/01/28 02:50:27 robertj
* Added missing bit shift operators to 64 bit integer class.
* Added assert into all Compare functions to assure comparison between compatible objects.
*
* Revision 1.16 1996/01/23 13:15:52 robertj
* Mac Metrowerks compiler support.
*
* Revision 1.15 1996/01/02 12:52:02 robertj
* Mac OS compatibility changes.
*
* Revision 1.14 1995/11/21 11:51:54 robertj
* Improved streams compatibility.
*
* Revision 1.12 1995/04/25 11:30:34 robertj
* Fixed Borland compiler warnings.
* Fixed function hiding ancestors virtual.
*
* Revision 1.11 1995/03/12 04:59:53 robertj
* Re-organisation of DOS/WIN16 and WIN32 platforms to maximise common code.
* Used built-in equate for WIN32 API (_WIN32).
*
* Revision 1.10 1995/02/19 04:19:21 robertj
* Added dynamically linked command processing.
*
* Revision 1.9 1995/01/15 04:52:02 robertj
* Mac compatibility.
* Added memory stats function.
*
// Revision 1.8 1995/01/09 12:38:07 robertj
// Changed variable names around during documentation run.
// Fixed smart pointer comparison.
// Fixed serialisation stuff.
//
// Revision 1.7 1995/01/07 04:39:45 robertj
// Redesigned font enumeration code and changed font styles.
//
// Revision 1.6 1995/01/04 10:57:08 robertj
// Changed for HPUX and GNU2.6.x
//
// Revision 1.5 1995/01/03 09:39:10 robertj
// Put standard malloc style memory allocation etc into memory check system.
//
// Revision 1.4 1994/12/21 11:43:29 robertj
// Added extra memory stats.
//
// Revision 1.3 1994/12/13 11:54:54 robertj
// Added some memory usage statistics.
//
// Revision 1.2 1994/12/12 10:08:32 robertj
// Renamed PWrapper to PSmartPointer..
//
// Revision 1.1 1994/10/30 12:02:15 robertj
// Initial revision
//
*/
#include <ptlib.h>
#include <ctype.h>
#ifdef _WIN32
#include <strstrea.h>
#include <ptlib/debstrm.h>
#else
#include <strstream.h>
#include <signal.h>
#endif
void PAssertFunc(const char * file, int line, PStandardAssertMessage msg)
{
static const char * const textmsg[PMaxStandardAssertMessage] = {
NULL,
"Out of memory",
"Null pointer reference",
"Invalid cast to non-descendant class",
"Invalid array index",
"Invalid array element",
"Stack empty",
"Unimplemented function",
"Invalid parameter",
"Operating System error",
"File not open",
"Unsupported feature",
"Invalid or closed operating system window"
};
const char * theMsg;
char msgbuf[20];
if (msg < PMaxStandardAssertMessage)
theMsg = textmsg[msg];
else {
sprintf(msgbuf, "Error code: %i", msg);
theMsg = msgbuf;
}
PAssertFunc(file, line, theMsg);
}
#if PMEMORY_CHECK
#undef malloc
#undef realloc
#undef free
void * operator new(size_t nSize)
{
return PMemoryHeap::Allocate(nSize, (const char *)NULL, 0, NULL);
}
void * operator new[](size_t nSize)
{
return PMemoryHeap::Allocate(nSize, (const char *)NULL, 0, NULL);
}
void operator delete(void * ptr)
{
PMemoryHeap::Deallocate(ptr, NULL);
}
void operator delete[](void * ptr)
{
PMemoryHeap::Deallocate(ptr, NULL);
}
DWORD PMemoryHeap::allocationBreakpoint;
const char PMemoryHeap::Header::GuardBytes[] =
{ '\x11', '\x55', '\x5a', '\xaa', '\xee', '\xaa', '\xa5', '\x55', '\x11' };
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_PTHREADS)
pthread_mutex_lock(&instance->mutex);
#endif
}
PMemoryHeap::Wrapper::~Wrapper()
{
if (instance->isDestroyed)
return;
#if defined(_WIN32)
LeaveCriticalSection(&instance->mutex);
#elif defined(P_PTHREADS)
pthread_mutex_unlock(&instance->mutex);
#endif
}
PMemoryHeap::PMemoryHeap()
{
isDestroyed = FALSE;
listHead = NULL;
listTail = NULL;
allocationRequest = 1;
firstRealObject = 0;
flags = 0;
allocFillChar = '\x5A';
freeFillChar = '\xA5';
currentMemoryUsage = 0;
peakMemoryUsage = 0;
currentObjects = 0;
peakObjects = 0;
totalObjects = 0;
#if defined(_WIN32)
InitializeCriticalSection(&mutex);
static PDebugStream debug;
leakDumpStream = &debug;
#else
#if defined(P_PTHREADS)
pthread_mutex_init(&mutex, NULL);
#endif
leakDumpStream = &cerr;
#endif
}
PMemoryHeap::~PMemoryHeap()
{
isDestroyed = TRUE;
if (leakDumpStream != NULL) {
DumpStatistics(*leakDumpStream);
#if !defined(_WIN32)
if (listTail != NULL && listTail->request >= firstRealObject) {
#if defined(P_PTHREADS)
sigset_t blockedSignals;
sigemptyset(&blockedSignals);
sigaddset(&blockedSignals, SIGINT);
sigaddset(&blockedSignals, SIGQUIT);
sigaddset(&blockedSignals, SIGTERM);
pthread_sigmask(SIG_UNBLOCK, &blockedSignals, NULL);
#endif
::signal(SIGINT, SIG_DFL);
::signal(SIGQUIT, SIG_DFL);
::signal(SIGTERM, SIG_DFL);
*leakDumpStream << "\nMemory leaks detected, press Enter to display . . ." << flush;
cin.get();
}
#endif
DumpObjectsSince(firstRealObject, *leakDumpStream);
}
#if defined(_WIN32)
DeleteCriticalSection(&mutex);
extern void PWaitOnExitConsoleWindow();
PWaitOnExitConsoleWindow();
#elif defined(P_PTHREADS)
pthread_mutex_destroy(&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;
}
if (firstRealObject == 0 && file != NULL && line > 0)
firstRealObject = allocationRequest;
PAssert(allocationRequest != allocationBreakpoint, "Break on memory allocation.");
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;
}
PAssert(mem->allocationRequest != allocationBreakpoint, "Break on memory allocation.");
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -