📄 object.cxx
字号:
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;
}
PBoolean 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 PFalse;
}
if (memcmp((char *)(obj+1)+obj->size, obj->GuardBytes, sizeof(obj->guard)) != 0) {
if (error != NULL)
*error << "Overrun at " << (obj+1) << '[' << obj->size << "] #" << obj->request << endl;
return PFalse;
}
obj = obj->next;
}
#if defined(_WIN32) && defined(_DEBUG)
if (!_CrtCheckMemory()) {
if (error != NULL)
*error << "Heap failed MSVCRT validation!" << endl;
return PFalse;
}
#endif
if (error != NULL)
*error << "Heap passed validation." << endl;
return PTrue;
}
PBoolean PMemoryHeap::SetIgnoreAllocations(PBoolean ignore)
{
Wrapper mem;
PBoolean ignoreAllocations = (mem->flags&NoLeakPrint) != 0;
if (ignore)
mem->flags |= NoLeakPrint;
else
mem->flags &= ~NoLeakPrint;
return ignoreAllocations;
}
void PMemoryHeap::DumpStatistics()
{
Wrapper mem;
if (mem->leakDumpStream != NULL)
mem->InternalDumpStatistics(*mem->leakDumpStream);
}
void PMemoryHeap::DumpStatistics(ostream & strm)
{
Wrapper mem;
mem->InternalDumpStatistics(strm);
}
void PMemoryHeap::InternalDumpStatistics(ostream & strm)
{
strm << "\nCurrent memory usage: " << currentMemoryUsage << " bytes";
if (currentMemoryUsage > 2048)
strm << ", " << (currentMemoryUsage+1023)/1024 << "kb";
if (currentMemoryUsage > 2097152)
strm << ", " << (currentMemoryUsage+1048575)/1048576 << "Mb";
strm << ".\nCurrent objects count: " << currentObjects
<< "\nPeak memory usage: " << peakMemoryUsage << " bytes";
if (peakMemoryUsage > 2048)
strm << ", " << (peakMemoryUsage+1023)/1024 << "kb";
if (peakMemoryUsage > 2097152)
strm << ", " << (peakMemoryUsage+1048575)/1048576 << "Mb";
strm << ".\nPeak objects created: " << peakObjects
<< "\nTotal objects created: " << totalObjects
<< "\nNext allocation request: " << allocationRequest
<< '\n' << endl;
}
void PMemoryHeap::GetState(State & state)
{
Wrapper mem;
state.allocationNumber = mem->allocationRequest;
}
void PMemoryHeap::SetAllocationBreakpoint(DWORD point)
{
allocationBreakpoint = point;
}
void PMemoryHeap::DumpObjectsSince(const State & state)
{
Wrapper mem;
if (mem->leakDumpStream != NULL)
mem->InternalDumpObjectsSince(state.allocationNumber, *mem->leakDumpStream);
}
void PMemoryHeap::DumpObjectsSince(const State & state, ostream & strm)
{
Wrapper mem;
mem->InternalDumpObjectsSince(state.allocationNumber, strm);
}
void PMemoryHeap::InternalDumpObjectsSince(DWORD objectNumber, ostream & strm)
{
PBoolean first = PTrue;
for (Header * obj = listHead; obj != NULL; obj = obj->next) {
if (obj->request < objectNumber || (obj->flags&NoLeakPrint) != 0)
continue;
if (first && isDestroyed) {
*leakDumpStream << "\nMemory leaks detected, press Enter to display . . ." << flush;
#if !defined(_WIN32)
cin.get();
#endif
first = PFalse;
}
BYTE * data = (BYTE *)&obj[1];
if (obj->fileName != NULL)
strm << obj->fileName << '(' << obj->line << ") : ";
strm << '#' << obj->request << ' ' << (void *)data << " [" << obj->size << "] ";
#ifdef P_LINUX
strm << '"' << PX_GetThreadName(obj->thread) << "\" ";
#endif
if (obj->className != NULL)
strm << '"' << obj->className << "\" ";
strm << '\n' << hex << setfill('0') << PBYTEArray(data, PMIN(16, obj->size), PFalse)
<< dec << setfill(' ') << endl;
}
}
#else // PMEMORY_CHECK
#if defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE)
static _CRT_DUMP_CLIENT pfnOldCrtDumpClient;
static bool hadCrtDumpLeak = false;
static void __cdecl MyCrtDumpClient(void * ptr, size_t size)
{
if(_CrtReportBlockType(ptr) == P_CLIENT_BLOCK) {
const PObject * obj = (PObject *)ptr;
_RPT1(_CRT_WARN, "Class %s\n", obj->GetClass());
hadCrtDumpLeak = true;
}
if (pfnOldCrtDumpClient != NULL)
pfnOldCrtDumpClient(ptr, size);
}
PMemoryHeap::PMemoryHeap()
{
_CrtMemCheckpoint(&initialState);
pfnOldCrtDumpClient = _CrtSetDumpClient(MyCrtDumpClient);
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & ~_CRTDBG_ALLOC_MEM_DF);
}
PMemoryHeap::~PMemoryHeap()
{
_CrtMemDumpAllObjectsSince(&initialState);
if (hadCrtDumpLeak) {
extern void PWaitOnExitConsoleWindow();
PWaitOnExitConsoleWindow();
}
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & ~_CRTDBG_LEAK_CHECK_DF);
}
static PMemoryHeap & MemoryHeapInstance()
{
static PMemoryHeap instance;
return instance;
}
void * PMemoryHeap::Allocate(size_t nSize, const char * file, int line, const char * className)
{
MemoryHeapInstance();
return _malloc_dbg(nSize, className != NULL ? P_CLIENT_BLOCK : _NORMAL_BLOCK, file, line);
}
void * PMemoryHeap::Allocate(size_t count, size_t iSize, const char * file, int line)
{
MemoryHeapInstance();
return _calloc_dbg(count, iSize, _NORMAL_BLOCK, file, line);
}
void * PMemoryHeap::Reallocate(void * ptr, size_t nSize, const char * file, int line)
{
MemoryHeapInstance();
return _realloc_dbg(ptr, nSize, _NORMAL_BLOCK, file, line);
}
void PMemoryHeap::Deallocate(void * ptr, const char * className)
{
_free_dbg(ptr, className != NULL ? P_CLIENT_BLOCK : _NORMAL_BLOCK);
}
PMemoryHeap::Validation PMemoryHeap::Validate(const void * ptr, const char * className, ostream * /*strm*/)
{
if (!_CrtIsValidHeapPointer(ptr))
return Bad;
if (_CrtReportBlockType(ptr) != P_CLIENT_BLOCK)
return Ok;
const PObject * obj = (PObject *)ptr;
return strcmp(obj->GetClass(), className) == 0 ? Ok : Trashed;
}
PBoolean PMemoryHeap::ValidateHeap(ostream * /*strm*/)
{
return _CrtCheckMemory();
}
PBoolean PMemoryHeap::SetIgnoreAllocations(PBoolean ignore)
{
int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
if (ignore)
_CrtSetDbgFlag(flags & ~_CRTDBG_ALLOC_MEM_DF);
else
_CrtSetDbgFlag(flags | _CRTDBG_ALLOC_MEM_DF);
return (flags & _CRTDBG_ALLOC_MEM_DF) == 0;
}
void PMemoryHeap::DumpStatistics()
{
_CrtMemState state;
_CrtMemCheckpoint(&state);
_CrtMemDumpStatistics(&state);
}
void PMemoryHeap::DumpStatistics(ostream & /*strm*/)
{
DumpStatistics();
}
void PMemoryHeap::GetState(State & state)
{
_CrtMemCheckpoint(&state);
}
void PMemoryHeap::DumpObjectsSince(const State & state)
{
_CrtMemDumpAllObjectsSince(&state);
}
void PMemoryHeap::DumpObjectsSince(const State & state, ostream & /*strm*/)
{
DumpObjectsSince(state);
}
void PMemoryHeap::SetAllocationBreakpoint(DWORD objectNumber)
{
_CrtSetBreakAlloc(objectNumber);
}
#else // defined(_MSC_VER) && defined(_DEBUG)
#if !defined(P_VXWORKS) && !defined(_WIN32_WCE)
#if (__GNUC__ >= 3) || ((__GNUC__ == 2)&&(__GNUC_MINOR__ >= 95)) //2.95.X & 3.X
void * operator new[](size_t nSize) throw (std::bad_alloc)
#else
void * operator new[](size_t nSize)
#endif
{
return malloc(nSize);
}
#if (__GNUC__ >= 3) || ((__GNUC__ == 2)&&(__GNUC_MINOR__ >= 95)) //2.95.X & 3.X
void operator delete[](void * ptr) throw ()
#else
void operator delete[](void * ptr)
#endif
{
free(ptr);
}
#endif // !P_VXWORKS
#endif // defined(_MSC_VER) && defined(_DEBUG)
#endif // PMEMORY_CHECK
///////////////////////////////////////////////////////////////////////////////
// Large integer support
#ifdef P_NEEDS_INT64
void PInt64__::Add(const PInt64__ & v)
{
unsigned long old = low;
high += v.high;
low += v.low;
if (low < old)
high++;
}
void PInt64__::Sub(const PInt64__ & v)
{
unsigned long old = low;
high -= v.high;
low -= v.low;
if (low > old)
high--;
}
void PInt64__::Mul(const PInt64__ & v)
{
DWORD p1 = (low&0xffff)*(v.low&0xffff);
DWORD p2 = (low >> 16)*(v.low >> 16);
DWORD p3 = (high&0xffff)*(v.high&0xffff);
DWORD p4 = (high >> 16)*(v.high >> 16);
low = p1 + (p2 << 16);
high = (p2 >> 16) + p3 + (p4 << 16);
}
void PInt64__::Div(const PInt64__ & v)
{
long double dividend = high;
dividend *= 4294967296.0;
dividend += low;
long double divisor = high;
divisor *= 4294967296.0;
divisor += low;
long double quotient = dividend/divisor;
low = quotient;
high = quotient/4294967296.0;
}
void PInt64__::Mod(const PInt64__ & v)
{
PInt64__ t = *this;
t.Div(v);
t.Mul(t);
Sub(t);
}
void PInt64__::ShiftLeft(int bits)
{
if (bits >= 32) {
high = low << (bits - 32);
low = 0;
}
else {
high <<= bits;
high |= low >> (32 - bits);
low <<= bits;
}
}
void PInt64__::ShiftRight(int bits)
{
if (bits >= 32) {
low = high >> (bits - 32);
high = 0;
}
else {
low >>= bits;
low |= high << (32 - bits);
high >>= bits;
}
}
PBoolean PInt64::Lt(const PInt64 & v) const
{
if ((long)high < (long)v.high)
return PTrue;
if ((long)high > (long)v.high)
return PFalse;
if ((long)high < 0)
return (long)low > (long)v.low;
return (long)low < (long)v.low;
}
PBoolean PInt64::Gt(const PInt64 & v) const
{
if ((long)high > (long)v.high)
return PTrue;
if ((long)high < (long)v.high)
return PFalse;
if ((long)high < 0)
return (long)low < (long)v.low;
return (long)low > (long)v.low;
}
PBoolean PUInt64::Lt(const PUInt64 & v) const
{
if (high < v.high)
return PTrue;
if (high > v.high)
return PFalse;
return low < high;
}
PBoolean PUInt64::Gt(const PUInt64 & v) const
{
if (high > v.high)
return PTrue;
if (high < v.high)
return PFalse;
return low > high;
}
static void Out64(ostream & stream, PUInt64 num)
{
char buf[25];
char * p = &buf[sizeof(buf)];
*--p = '\0';
switch (stream.flags()&ios::basefield) {
case ios::oct :
while (num != 0) {
*--p = (num&7) + '0';
num >>= 3;
}
break;
case ios::hex :
while (num != 0) {
*--p = (num&15) + '0';
if (*p > '9')
*p += 7;
num >>= 4;
}
break;
default :
while (num != 0) {
*--p = num%10 + '0';
num /= 10;
}
}
if (*p == '\0')
*--p = '0';
stream << p;
}
ostream & operator<<(ostream & stream, const PInt64 & v)
{
if (v >= 0)
Out64(stream, v);
else {
int w = stream.width();
stream.put('-');
if (w > 0)
stream.width(w-1);
Out64(stream, -v);
}
return stream;
}
ostream & operator<<(ostream & stream, const PUInt64 & v)
{
Out64(stream, v);
return stream;
}
static PUInt64 Inp64(istream & stream)
{
int base;
switch (stream.flags()&ios::basefield) {
case ios::oct :
base = 8;
break;
case ios::hex :
base = 16;
break;
default :
base = 10;
}
if (isspace(stream.peek()))
stream.get();
PInt64 num = 0;
while (isxdigit(stream.peek())) {
int c = stream.get() - '0';
if (c > 9)
c -= 7;
if (c > 9)
c -= 32;
num = num*base + c;
}
return num;
}
istream & operator>>(istream & stream, PInt64 & v)
{
if (isspace(stream.peek()))
stream.get();
switch (stream.peek()) {
case '-' :
stream.ignore();
v = -(PInt64)Inp64(stream);
break;
case '+' :
stream.ignore();
default :
v = (PInt64)Inp64(stream);
}
return stream;
}
istream & operator>>(istream & stream, PUInt64 & v)
{
v = Inp64(stream);
return stream;
}
#endif
#ifdef P_TORNADO
// the library provided with Tornado 2.0 does not contain implementation
// for the functions defined below, therefor the own implementation
ostream & ostream::operator<<(PInt64 v)
{
return *this << (long)(v >> 32) << (long)(v & 0xFFFFFFFF);
}
ostream & ostream::operator<<(PUInt64 v)
{
return *this << (long)(v >> 32) << (long)(v & 0xFFFFFFFF);
}
istream & istream::operator>>(PInt64 & v)
{
return *this >> (long)(v >> 32) >> (long)(v & 0xFFFFFFFF);
}
istream & istream::operator>>(PUInt64 & v)
{
return *this >> (long)(v >> 32) >> (long)(v & 0xFFFFFFFF);
}
#endif // P_TORNADO
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -