void JMMHashTable::_AddNewRecord ( const JMMRecord& record, const JBoolean checkDoubleAllocation ) { JHashCursor<JMMRecord> cursor(itsAllocatedTable, reinterpret_cast<JHashValue>( record.GetAddress() ) ); if (checkDoubleAllocation) { cursor.ForceNextMapInsertHash(); if ( cursor.IsFull() ) { JMMRecord thisRecord = cursor.GetValue(); itsAllocatedBytes -= thisRecord.GetSize(); NotifyMultipleAllocation(record, thisRecord); } // Might as well trust malloc--the table should never have duplicate // entries! } else { cursor.ForceNextOpen(); } cursor.Set(reinterpret_cast<JHashValue>( record.GetAddress() ), record); itsAllocatedBytes += record.GetSize(); }
void JMMArrayTable::_AddNewRecord ( const JMMRecord& record, const JBoolean checkDoubleAllocation ) { JSize index = 0; if (checkDoubleAllocation) { index = FindAllocatedBlock( record.GetAddress() ); } if (index == 0) { // Append because new allocations tend to be free'd the fastest itsAllocatedTable->AppendElement(record); } else { JMMRecord thisRecord = itsAllocatedTable->GetElement(index); itsAllocatedBytes -= thisRecord.GetSize(); NotifyMultipleAllocation(record, thisRecord); // Might as well trust malloc--the table should never have duplicate // entries! itsAllocatedTable->SetElement(index, record); } itsAllocatedBytes += record.GetSize(); }
JBoolean JMMArrayTable::_SetRecordDeleted ( JMMRecord* record, const void* block, const JCharacter* file, const JUInt32 line, const JBoolean isArray ) { JSize index = FindAllocatedBlock(block); if (index != 0) { JMMRecord thisRecord = itsAllocatedTable->GetElement(index); thisRecord.SetDeleteLocation(file, line, isArray); itsAllocatedBytes -= thisRecord.GetSize(); if (!thisRecord.ArrayNew() && isArray) { NotifyObjectDeletedAsArray(thisRecord); } else if (thisRecord.ArrayNew() && !isArray) { NotifyArrayDeletedAsObject(thisRecord); } itsAllocatedTable->RemoveElement(index); if (itsDeletedTable != NULL) { itsDeletedTable->AppendElement(thisRecord); } else { itsDeletedCount++; } *record = thisRecord; return kJTrue; } else { // Because the array is searched backwards, if it finds a block it // will be the most recent deallocation at that address index = FindDeletedBlock(block); if (index == 0) { NotifyUnallocatedDeletion(file, line, isArray); } else { JMMRecord thisRecord = itsDeletedTable->GetElement(index); NotifyMultipleDeletion(thisRecord, file, line, isArray); } return kJFalse; } }
void JMMErrorPrinter::HandleArrayDeletedAsObject ( const JMMRecord& record ) { if (itsPrintErrorsFlag) { cout << "*** memory error: Block allocated as array at\n " << record.GetNewFile() << ":" << record.GetNewLine() << "\n was deleted as object at\n " << record.GetDeleteFile() << ":" << record.GetDeleteLine() << endl; } }
void JMMErrorPrinter::HandleMultipleDeletion ( const JMMRecord& originalRecord, const JCharacter* file, const JUInt32 line, const JBoolean isArray ) { if (itsPrintErrorsFlag) { cout << "*** memory error: Block deleted as " << JMMRecord::TypeName(isArray) << " at\n " << file << ":" << line << "\n was already deleted, most recently as " << originalRecord.DeleteTypeName() << " at\n " << originalRecord.GetDeleteFile() << ":" << originalRecord.GetDeleteLine() << endl; } }
JSize JMMArrayTable::FindAllocatedBlock ( const void* block ) const { JSize allocatedCount = itsAllocatedTable->GetElementCount(); for (JSize i=allocatedCount;i>=1;i--) { const JMMRecord thisRecord = itsAllocatedTable->GetElement(i); if (thisRecord.GetAddress() == block) { return i; } } return 0; }
void JMMHashTable::PrintAllocated ( const JBoolean printInternal // = kJFalse ) const { cout << "\nAllocated block statistics:" << endl; cout << "\nAllocated user memory:" << endl; JConstHashCursor<JMMRecord> cursor(itsAllocatedTable); JSize totalSize = 0; while ( cursor.NextFull() ) { const JMMRecord thisRecord = cursor.GetValue(); if ( !thisRecord.IsManagerMemory() ) { PrintAllocatedRecord(thisRecord); totalSize += thisRecord.GetSize(); } } cout << "\nTotal allocated memory: " << totalSize << " bytes" << endl; if (printInternal) { cout << "\nThe following blocks are probably owned by the memory manager" << "\nand *should* still be allocated--please report all cases of user" << "\nallocated memory showing up on this list!" << endl; cursor.Reset(); while ( cursor.NextFull() ) { const JMMRecord thisRecord = cursor.GetValue(); if ( thisRecord.IsManagerMemory() ) { PrintAllocatedRecord(thisRecord); } } } }
void JMemoryManager::DeleteRecord ( void* block, const JCharacter* file, const JUInt32 line, const JBoolean isArray ) { if (block == NULL) { HandleNULLDeleted(file, line, isArray); } else { JBoolean wasAllocated; if (itsMemoryTable != NULL) { JMMRecord record; wasAllocated = itsMemoryTable->SetRecordDeleted(&record, block, file, line, isArray); // Can't do this unless we're keeping records if (itsShredFlag && wasAllocated) { assert(record.GetAddress() == block); memset(block, itsDeallocateGarbage, record.GetSize() ); } } else { wasAllocated = kJTrue; // Have to trust the client } // Try to avoid a seg fault so the program can continue if (wasAllocated) { free(block); } } }
JSize JMMArrayTable::FindDeletedBlock ( const void* block ) const { if (itsDeletedTable != NULL) { JSize deletedCount = itsDeletedTable->GetElementCount(); for (JSize i=deletedCount;i>=1;i--) { const JMMRecord thisRecord = itsDeletedTable->GetElement(i); if (thisRecord.GetAddress() == block) { return i; } } } return 0; }
void JMMArrayTable::StreamAllocatedForDebug ( ostream& output, const JMemoryManager::RecordFilter& filter ) const { const JSize count = itsAllocatedTable->GetElementCount(); for (JIndex i=1;i<=count;i++) { const JMMRecord thisRecord = itsAllocatedTable->GetElement(i); if (filter.Match(thisRecord)) { output << ' ' << kJTrue; output << ' '; thisRecord.StreamForDebug(output); } } output << ' ' << kJFalse; }
void JMMHashTable::StreamAllocatedForDebug ( ostream& output, const JMemoryManager::RecordFilter& filter ) const { JConstHashCursor<JMMRecord> cursor(itsAllocatedTable); JSize totalSize = 0; while ( cursor.NextFull() ) { const JMMRecord thisRecord = cursor.GetValue(); if (filter.Match(thisRecord)) { output << ' ' << kJTrue; output << ' '; thisRecord.StreamForDebug(output); } } output << ' ' << kJFalse; }
void JMMArrayTable::PrintAllocated ( const JBoolean printInternal // = kJFalse ) const { cout << "\nAllocated block statistics:" << endl; cout << "\nAllocated user memory:" << endl; const JSize count = itsAllocatedTable->GetElementCount(); for (JIndex i=1;i<=count;i++) { const JMMRecord thisRecord = itsAllocatedTable->GetElement(i); if ( !thisRecord.IsManagerMemory() ) { PrintAllocatedRecord(thisRecord); } } if (printInternal) { cout << "\nThe following blocks are probably owned by the memory manager" << "\nand *should* still be allocated--please report all cases of user" << "\nallocated memory showing up on this list!" << endl; for (JIndex i=1;i<=count;i++) { const JMMRecord thisRecord = itsAllocatedTable->GetElement(i); if ( thisRecord.IsManagerMemory() ) { PrintAllocatedRecord(thisRecord); } } } }
JBoolean JMemoryManager::RecordFilter::Match ( const JMMRecord& record ) const { JBoolean match = kJTrue; if (!includeInternal && record.IsManagerMemory()) { match = kJFalse; } if (record.GetSize() < minSize) { match = kJFalse; } const JSize newFileLength = strlen(record.GetNewFile()); if (match && fileName != NULL && newFileLength == fileName->GetLength()) { if (record.GetNewFile() != *fileName) { match = kJFalse; } } else if (match && fileName != NULL) { const JCharacter *s1, *s2; JSize l1, l2; if (newFileLength > fileName->GetLength()) { s1 = record.GetNewFile(); l1 = newFileLength; s2 = *fileName; l2 = fileName->GetLength(); } else { s1 = *fileName; l1 = fileName->GetLength(); s2 = record.GetNewFile(); l2 = newFileLength; } if (*(s1 + l1 - l2 - 1) != ACE_DIRECTORY_SEPARATOR_CHAR || strcmp(s1 + l1 - l2, s2) != 0) { match = kJFalse; } } return match; }
void JMMErrorPrinter::HandleMultipleAllocation ( const JMMRecord& thisRecord, const JMMRecord& firstRecord ) { if (itsPrintErrorsFlag) { cout << "*** memory error: item allocated as " << thisRecord.DeleteTypeName() << " at\n " << thisRecord.GetNewFile() << ":" << thisRecord.GetNewLine() << "\n was first allocated as " << firstRecord.DeleteTypeName() << " at\n " << firstRecord.GetNewFile() << ":" << firstRecord.GetNewLine() << endl; } }
JBoolean JMMHashTable::_SetRecordDeleted ( JMMRecord* record, const void* block, const JCharacter* file, const JUInt32 line, const JBoolean isArray ) { JHashCursor<JMMRecord> allocCursor(itsAllocatedTable, reinterpret_cast<JHashValue>(block) ); if ( allocCursor.NextHash() ) { JMMRecord thisRecord = allocCursor.GetValue(); thisRecord.SetDeleteLocation(file, line, isArray); itsAllocatedBytes -= thisRecord.GetSize(); if (!thisRecord.ArrayNew() && isArray) { NotifyObjectDeletedAsArray(thisRecord); } else if (thisRecord.ArrayNew() && !isArray) { NotifyArrayDeletedAsObject(thisRecord); } allocCursor.Remove(); if (itsDeletedTable != NULL) { JHashCursor<JMMRecord> deallocCursor(itsDeletedTable, reinterpret_cast<JHashValue>(block) ); deallocCursor.ForceNextOpen(); deallocCursor.Set(reinterpret_cast<JHashValue>(block), thisRecord); } else { itsDeletedCount++; } *record = thisRecord; return kJTrue; } else { if (itsDeletedTable == NULL) { NotifyUnallocatedDeletion(file, line, isArray); } else { JHashCursor<JMMRecord> deallocCursor(itsDeletedTable, reinterpret_cast<JHashValue>(block) ); if ( deallocCursor.NextHash() ) { // Seek most recent deallocation at that address JMMRecord previousRecord = deallocCursor.GetValue(); while ( deallocCursor.NextHash() ) { JMMRecord thisRecord = deallocCursor.GetValue(); if ( thisRecord.GetID() > previousRecord.GetID() ) { previousRecord = thisRecord; } } NotifyMultipleDeletion(previousRecord, file, line, isArray); } else { NotifyUnallocatedDeletion(file, line, isArray); } } return kJFalse; } }