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;
}
Example #14
0
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;
    }
}