📄 object.cxx
字号:
void PMemoryHeap::Deallocate(void * ptr, const char * className)
{
if (ptr == NULL)
return;
Wrapper mem;
if (mem->isDestroyed) {
free(ptr);
return;
}
if (mem->InternalValidate(ptr, className, mem->leakDumpStream) != Ok) {
free(ptr);
return;
}
Header * obj = ((Header *)ptr)-1;
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;
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 (obj->className != NULL && strcmp(obj->className, className) != 0) {
if (error != NULL)
*error << "PObject " << ptr << '[' << obj->size << "] #" << obj->request
<< " allocated as \"" << obj->className
<< "\" and should be \"" << className << "\"." << endl;
return Bad;
}
Header * forward = obj;
Header * backward = obj;
while (forward->next != NULL && backward->prev != NULL) {
forward = forward->next;
backward = backward->prev;
}
if (forward != listTail && backward != listHead) {
if (error != NULL)
*error << "Block " << ptr << '[' << obj->size << "] #" << obj->request
<< " not in heap!" << endl;
return Trashed;
}
return Ok;
}
void PMemoryHeap::SetIgnoreAllocations(BOOL ignore)
{
Wrapper mem;
if (ignore)
mem->flags |= NoLeakPrint;
else
mem->flags &= ~NoLeakPrint;
}
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
<< '\n' << endl;
}
DWORD PMemoryHeap::GetAllocationRequest()
{
Wrapper mem;
return mem->allocationRequest;
}
void PMemoryHeap::SetAllocationBreakpoint(DWORD point)
{
allocationBreakpoint = point;
}
void PMemoryHeap::DumpObjectsSince(DWORD objectNumber)
{
Wrapper mem;
if (mem->leakDumpStream != NULL)
mem->InternalDumpObjectsSince(objectNumber, *mem->leakDumpStream);
}
void PMemoryHeap::DumpObjectsSince(DWORD objectNumber, ostream & strm)
{
Wrapper mem;
mem->InternalDumpObjectsSince(objectNumber, strm);
}
void PMemoryHeap::InternalDumpObjectsSince(DWORD objectNumber, ostream & strm)
{
for (Header * obj = listHead; obj != NULL; obj = obj->next) {
if (obj->request < objectNumber || (obj->flags&NoLeakPrint) != 0)
continue;
BYTE * data = (BYTE *)&obj[1];
if (obj->fileName != NULL)
strm << obj->fileName << '(' << obj->line << ") : ";
strm << '#' << obj->request << ' ' << (void *)data << " [" << obj->size << "] ";
if (obj->className != NULL)
strm << '"' << obj->className << "\" ";
strm << '\n' << hex << setfill('0') << PBYTEArray(data, PMIN(16, obj->size), FALSE)
<< dec << setfill(' ') << endl;
}
}
#endif
const char * PObject::GetClass(unsigned) const
{
return Class();
}
BOOL PObject::IsClass(const char * clsName) const
{
return strcmp(clsName, Class()) == 0;
}
BOOL PObject::IsDescendant(const char * clsName) const
{
return strcmp(clsName, Class()) == 0;
}
PObject::Comparison PObject::CompareObjectMemoryDirect(const PObject&obj) const
{
int retval = memcmp(this, &obj, sizeof(PObject));
if (retval < 0)
return LessThan;
if (retval > 0)
return GreaterThan;
return EqualTo;
}
PObject * PObject::Clone() const
{
PAssertAlways(PUnimplementedFunction);
return NULL;
}
PObject::Comparison PObject::Compare(const PObject & obj) const
{
return (Comparison)CompareObjectMemoryDirect(obj);
}
void PObject::PrintOn(ostream & strm) const
{
strm << GetClass();
}
void PObject::ReadFrom(istream &)
{
}
PINDEX PObject::PreSerialise(PSerialiser &)
{
return 0;
}
void PObject::Serialise(PSerialiser &)
{
}
void PObject::UnSerialise(PUnSerialiser &)
{
}
PINDEX PObject::HashFunction() const
{
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// Serialisation support
PSerialRegistration * PSerialRegistration::creatorHashTable[
PSerialRegistration::HashTableSize];
PINDEX PSerialRegistration::HashFunction(const char * className)
{
PINDEX hash = (BYTE)className[0];
if (className[0] != '\0') {
hash += (BYTE)className[1];
if (className[1] != '\0')
hash += (BYTE)className[2];
}
return hash%HashTableSize;
}
PSerialRegistration::PSerialRegistration(const char * clsNam,
CreatorFunction func)
: className(clsNam), creator(func)
{
clash = NULL;
PINDEX hash = HashFunction(className);
if (creatorHashTable[hash] != NULL)
creatorHashTable[hash]->clash = this;
creatorHashTable[hash] = this;
}
PSerialRegistration::CreatorFunction
PSerialRegistration::GetCreator(const char * clsNam)
{
PINDEX hash = HashFunction(clsNam);
PSerialRegistration * reg = creatorHashTable[hash];
while (reg != NULL) {
if (strcmp(reg->className, clsNam) == 0)
return reg->creator;
}
return NULL;
}
PSerialiser::PSerialiser(ostream & strm)
: stream(strm)
{
}
PSerialiser & PSerialiser::operator<<(PObject & obj)
{
obj.Serialise(*this);
return *this;
}
PTextSerialiser::PTextSerialiser(ostream & strm, PObject & data)
: PSerialiser(strm)
{
data.Serialise(*this);
}
PSerialiser & PTextSerialiser::operator<<(char)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(unsigned char)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(signed char)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(short)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(unsigned short)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(int)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(unsigned int)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(long)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(unsigned long)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(float)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(double)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(long double)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(const char *)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(const unsigned char *)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(const signed char *)
{ return *this; }
PSerialiser & PTextSerialiser::operator<<(PObject & obj)
{ return PSerialiser::operator<<(obj); }
PBinarySerialiser::PBinarySerialiser(ostream & strm, PObject & data)
: PSerialiser(strm)
{
classesUsed = new PSortedStringList;
data.PreSerialise(*this);
stream << *classesUsed;
data.Serialise(*this);
}
PBinarySerialiser::~PBinarySerialiser()
{
delete classesUsed;
}
PSerialiser & PBinarySerialiser::operator<<(char)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(unsigned char)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(signed char)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(short)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(unsigned short)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(int)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(unsigned int)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(long)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(unsigned long)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(float)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(double)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(long double)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(const char *)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(const unsigned char *)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(const signed char *)
{ return *this; }
PSerialiser & PBinarySerialiser::operator<<(PObject & obj)
{ return PSerialiser::operator<<(obj); }
PUnSerialiser::PUnSerialiser(istream & strm)
: stream(strm)
{
}
PTextUnSerialiser::PTextUnSerialiser(istream & strm)
: PUnSerialiser(strm)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -