Initial source commit

This commit is contained in:
Tony Bark 2025-10-03 02:19:59 -04:00
commit f1384c11ee
335 changed files with 52715 additions and 0 deletions

View file

@ -0,0 +1,277 @@
/*
* Modification History
*
* 2002-October-17 Jason Rohrer
* Created.
*
* 2002-October-18 Jason Rohrer
* Changed to use custom list instead of SimpleVector because SimpleVector
* uses debugMemory.
* Added static initialization counting class.
* Changed to use struct and malloc for AllocationList to avoid
* circular new and delete calls.
*
* 2002-October-19 Jason Rohrer
* Fixed a bug in adding to the alloc list.
* Improved printing behavior.
* Added support for clearing memory on allocation and deallocation.
* Fixed to ignore deallocation of our own static lock.
* Fixed bug in allocation count.
* Added message for NULL pointer deallocation.
* Put locks in place around print statements, which are not atomic on win32.
* Changed to use hex notation when printing pointers.
*
* 2002-October-19 Jason Rohrer
* Added ifdef for DEBUG_MEMORY.
*
* 2002-October-20 Jason Rohrer
* Removed file and line arguments from deallocation calls.
*/
#ifdef DEBUG_MEMORY
#include "minorGems/util/development/memory/MemoryTrack.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int MemoryTrackStaticInitCounter::mCount = 0;
MutexLock *MemoryTrack::mLock;
AllocationList *MemoryTrack::mListHead;
char MemoryTrack::mTracking = false;
int MemoryTrack::mTotalAllocationSize = 0;
int MemoryTrack::mTotalDeallocationSize = 0;
int MemoryTrack::mNumberOfAllocations = 0;
void MemoryTrack::addAllocation( void *inPointer,
unsigned int inAllocationSize,
int inAllocationType,
const char *inFileName,
int inLineNumber ) {
mLock->lock();
if( !mTracking ) {
printf( "Tracking off on allocation (0x%x) [%d bytes] %s:%d.\n",
(unsigned int)inPointer,
inAllocationSize,
inFileName, inLineNumber );
mLock->unlock();
return;
}
// insert after head of list
AllocationList *element =
(AllocationList *)malloc( sizeof( AllocationList ) );
element->mPrevious = (void *)mListHead;
element->mNext = mListHead->mNext;
mListHead->mNext = (void *)element;
AllocationList *nextElement = (AllocationList *)( element->mNext );
if( nextElement != NULL ) {
nextElement->mPrevious = (void *)element;
}
element->mPointer = inPointer;
element->mAllocationSize = inAllocationSize;
element->mAllocationType = inAllocationType;
element->mFileName = inFileName;
element->mLineNumber = inLineNumber;
mTotalAllocationSize += inAllocationSize;
mNumberOfAllocations ++;
// wipe this block of memory
clearMemory( inPointer, inAllocationSize );
mLock->unlock();
}
int MemoryTrack::addDeallocation( void *inPointer,
int inDeallocationType ) {
mLock->lock();
if( inPointer == NULL ) {
printf( "NULL pointer (0x%x) deallocated\n",
(unsigned int)inPointer );
}
if( inPointer == (void *)mLock ) {
// we're seeing the deallocation of our own static lock as
// the system exits
// ignore it
mLock->unlock();
return 0;
}
if( !mTracking ) {
printf( "Tracking off on deallocation (0x%x)\n",
(unsigned int)inPointer );
mLock->unlock();
return 0;
}
AllocationList *element = (AllocationList *)( mListHead->mNext );
while( element != NULL ) {
void *pointer = element->mPointer;
if( pointer == inPointer ) {
unsigned int allocationSize = element->mAllocationSize;
int allocationType = element->mAllocationType;
const char *allocFileName = element->mFileName;
int allocLineNumber = element->mLineNumber;
// remove from list, whether or not types match
AllocationList *previousElement =
(AllocationList *)( element->mPrevious );
AllocationList *nextElement =
(AllocationList *)( element->mNext );
// patch list
previousElement->mNext = (void *)( nextElement );
if( nextElement != NULL ) {
nextElement->mPrevious = (void *)( previousElement );
}
free( element );
mTotalDeallocationSize += allocationSize;
if( allocationType == inDeallocationType ) {
// found and types match
mLock->unlock();
// wipe this block of memory
clearMemory( inPointer, allocationSize );
return 0;
}
else {
// allocation types don't match
printf( "Attempt to deallocate (0x%x) [%d bytes] with wrong"
" delete form\n"
" %s:%d (location of original allocation)\n",
(unsigned int)inPointer,
allocationSize,
allocFileName, allocLineNumber );
mLock->unlock();
return 2;
}
}
element = (AllocationList *)( element->mNext );
}
// not found (delete of unallocated memory)
printf( "Attempt to deallocate (0x%x) unallocated memory\n",
(unsigned int)inPointer );
mLock->unlock();
return 1;
}
void MemoryTrack::printLeaks() {
mLock->lock();
printf( "\n\n---- debugMemory report ----\n" );
printf( "Number of Allocations: %d\n", mNumberOfAllocations );
printf( "Total allocations: %d bytes\n", mTotalAllocationSize );
printf( "Total deallocations: %d bytes\n", mTotalDeallocationSize );
int leakEstimate = mTotalAllocationSize - mTotalDeallocationSize;
AllocationList *element = (AllocationList *)( mListHead->mNext );
if( element == NULL ) {
printf( "No leaks detected.\n" );
}
else {
printf( "Leaks detected:\n" );
}
int leakSum = 0;
while( element != NULL ) {
printf( "Not deallocated (0x%x) [%d bytes]\n"
" %s:%d (location of original allocation)\n",
(unsigned int)( element->mPointer ),
element->mAllocationSize,
element->mFileName,
element->mLineNumber );
leakSum += element->mAllocationSize;
element = (AllocationList *)( element->mNext );
}
if( leakSum != leakEstimate ) {
printf( "Warning: Leak sum does not equal leak estimate.\n" );
}
printf( "Leaked memory: %d bytes\n", leakSum );
printf( "---- END debugMemory report ----\n\n" );
mLock->unlock();
}
void MemoryTrack::clearMemory( void *inPointer, unsigned int inSize ) {
unsigned char *charArray = (unsigned char *)inPointer;
for( unsigned int i=0; i<inSize; i++ ) {
charArray[i] = (unsigned char)0xAA;
}
}
#endif

View file

@ -0,0 +1,230 @@
/*
* Modification History
*
* 2002-October-17 Jason Rohrer
* Created.
*
* 2002-October-18 Jason Rohrer
* Changed to use custom list instead of SimpleVector because SimpleVector
* uses debugMemory.
* Added static initialization counting class.
* Changed to use struct and malloc for AllocationList to avoid
* circular new and delete calls.
*
* 2002-October-19 Jason Rohrer
* Changed to print leak list upon final destruction.
* Improved printing behavior.
* Added support for clearing memory on allocation and deallocation.
*
* 2002-October-20 Jason Rohrer
* Removed file and line arguments from deallocation calls.
*/
#ifndef MEMORY_TRACK_INCLUDED
#define MEMORY_TRACK_INCLUDED
#include "minorGems/system/MutexLock.h"
#include <stdio.h>
#include <stdlib.h>
#define SINGLE_ALLOCATION 0
#define ARRAY_ALLOCATION 1
/**
* Linked list of memory allocations.
*
* @author Jason Rohrer
*/
typedef struct {
void *mPrevious;
void *mNext;
void *mPointer;
unsigned int mAllocationSize;
int mAllocationType;
const char *mFileName;
int mLineNumber;
} AllocationList;
/**
* Class that tracks memory allocations and deallocations.
*
* @author Jason Rohrer
*/
class MemoryTrack {
public:
/**
* Adds an allocation to this tracker and clears the allocated
* memory block.
*
* @param inPointer a pointer to the allocated memory.
* @param inAllocationType the type of allocation,
* either SINGLE_ALLOCATION or ARRAY_ALLOCATION.
* @param inAllocationSize the size of the allocation in bytes.
* @param inFileName the name of the source file in which the
* allocation took place.
* @param inLineNumber the line number in the source file
* on which the allocation took place.
*/
static void addAllocation( void *inPointer,
unsigned int inAllocationSize,
int inAllocationType,
const char *inFileName,
int inLineNumber );
/**
* Adds a deallocation to this tracker and clears the block
* to be deallocated.
* Must be called *before* the memory is deallocated
*
* @param inPointer a pointer to the memory being deallocated.
* @param inDeallocationType the type of deallocation,
* either SINGLE_ALLOCATION or ARRAY_ALLOCATION.
* @return 0 if the deallocation deallocates
* an allocated block of memory, or 1 if it
* deallocates a block of memory that is not currently allocated,
* and 2 if it is the wrong deallocation type for the specified
* block.
*/
static int addDeallocation( void *inPointer, int inDeallocationType );
/**
* Prints a list of all memory leaks (allocations that have never
* been deallocated).
*/
static void printLeaks();
// these are public so initializer can get to them
static MutexLock *mLock;
// dummy place holder for list head
static AllocationList *mListHead;
// true if we're tracking
static char mTracking;
static int mTotalAllocationSize;
static int mTotalDeallocationSize;
static int mNumberOfAllocations;
protected:
/**
* Clears memory so that reading from it will not produce
* anything useful. Good for checking for reads to memory that
* has been deallocated.
*
* @param inPointer pointer to the memory to clear.
* @Param inSize the number of bytes to clear starting at inPointer.
*/
static void clearMemory( void *inPointer, unsigned int inSize );
};
/**
* Class that initializes MemoryTrack's static members.
*
* *All* files that use MemoryTrack will instantiate a static
* instance of this class (see static instance below).
*
* This class counts how many static instantiations have happened so
* far, making sure to init/destroy MemoryTrack's static members only once.
*
* Adapted from:
* http://www.hlrs.de/organization/par/services/tools/docu/kcc/
* tutorials/static_initialization.html
*/
class MemoryTrackStaticInitCounter {
public:
MemoryTrackStaticInitCounter() {
if( mCount == 0 ) {
// allocate static members
MemoryTrack::mLock = new MutexLock();
MemoryTrack::mListHead =
(AllocationList *)
malloc( sizeof( AllocationList ) );
MemoryTrack::mListHead->mPrevious = NULL;
MemoryTrack::mListHead->mNext = NULL;
MemoryTrack::mTotalAllocationSize = 0;
MemoryTrack::mTotalDeallocationSize = 0;
MemoryTrack::mNumberOfAllocations = 0;
MemoryTrack::mTracking = true;
}
mCount++;
}
~MemoryTrackStaticInitCounter() {
mCount--;
if( mCount == 0 ) {
// print leaks... we should only get here after
// all static members of classes that use MemoryTrack
// have been destroyed.
MemoryTrack::printLeaks();
MemoryTrack::mTracking = false;
// deallocate static members
free( MemoryTrack::mListHead );
delete MemoryTrack::mLock;
}
}
private:
// only allocate/deallocate when mCount == 0
static int mCount;
};
// This will be included in *every* file that includes MemoryTrack.h
static MemoryTrackStaticInitCounter memoryTrackInitializer;
#endif

View file

@ -0,0 +1 @@
g++ -Wall -g -DDEBUG_MEMORY -o testDebugMemory -I../../../.. debugMemory.cpp MemoryTrack.cpp testDebugMemory.cpp ../../../../minorGems/system/linux/MutexLockLinux.cpp

View file

@ -0,0 +1,95 @@
/*
* Modification History
*
* 2002-October-17 Jason Rohrer
* Created.
*
* 2002-October-18 Jason Rohrer
* Added static initialization counting class for MemoryTrack.
*
* 2002-October-19 Jason Rohrer
* Added more detail to error message.
* Improved printing behavior.
* Moved include of debugMemory.h to work better with IDE compilers.
* Fixed to deal with differences between malloc and new[] on some platforms.
*
* 2002-October-20 Jason Rohrer
* Removed delete macro trick that was causing crashes in tinyxml.
* Removed function that was no longer being used.
*/
#include "minorGems/util/development/memory/debugMemory.h"
#ifdef DEBUG_MEMORY
#include "minorGems/util/development/memory/MemoryTrack.h"
#include "stdlib.h"
#include "stdio.h"
void *debugMemoryNew( unsigned int inSize,
const char *inFileName, int inLine ) {
void *allocatedPointer = (void *)malloc( inSize );
MemoryTrack::addAllocation( allocatedPointer, inSize,
SINGLE_ALLOCATION,
inFileName, inLine );
return allocatedPointer;
}
void *debugMemoryNewArray( unsigned int inSize,
const char *inFileName, int inLine ) {
unsigned int mallocSize = inSize;
if( inSize == 0 ) {
// always allocate at least one byte to circumvent differences
// between malloc and new[] on some platforms
// (new int[0] returns a pointer to an array of length 0, while
// malloc( 0 ) can return NULL on some platforms)
mallocSize = 1;
}
void *allocatedPointer = (void *)malloc( mallocSize );
MemoryTrack::addAllocation( allocatedPointer, inSize,
ARRAY_ALLOCATION,
inFileName, inLine );
return allocatedPointer;
}
void debugMemoryDelete( void *inPointer ) {
MemoryTrack::addDeallocation( inPointer, SINGLE_ALLOCATION );
free( inPointer );
}
void debugMemoryDeleteArray( void *inPointer ) {
MemoryTrack::addDeallocation( inPointer, ARRAY_ALLOCATION );
free( inPointer );
}
#endif

View file

@ -0,0 +1,127 @@
/*
* Modification History
*
* 2002-October-17 Jason Rohrer
* Created.
*
* 2002-October-18 Jason Rohrer
* Added static initialization counting class for MemoryTrack.
*
* 2002-October-20 Jason Rohrer
* Removed delete macro trick that was causing crashes in tinyxml.
*/
#ifndef DEBUG_MEMORY_INCLUDED
#define DEBUG_MEMORY_INCLUDED
#ifdef DEBUG_MEMORY
#include "minorGems/util/development/memory/MemoryTrack.h"
// internal function prototypes
void *debugMemoryNew( unsigned int inSize,
const char *inFileName, int inLine );
void *debugMemoryNewArray( unsigned int inSize,
const char *inFileName, int inLine );
void debugMemoryDelete( void *inPointer );
void debugMemoryDeleteArray( void *inPointer );
// overrided primitive operators... must be inline?
/**
* Overrides the new operator to track memory allocations.
*
* @param inSize the size of the allocation.
* @param inFileName the name of the source file where the allocation
* occurred.
* @param inLine the line in the source file where the allocation occurred.
*/
inline void *operator new( unsigned int inSize,
const char *inFileName, int inLine ) {
return debugMemoryNew( inSize, inFileName, inLine );
}
/**
* Overrides the new [] operator to track memory allocations.
*
* @param inSize the size of the allocation.
* @param inFileName the name of the source file where the allocation
* occurred.
* @param inLine the line in the source file where the allocation occurred.
*/
inline void * operator new [] ( unsigned int inSize,
const char *inFileName, int inLine ) {
return debugMemoryNewArray( inSize, inFileName, inLine );
}
/**
* Overrides the delete operator to track memory allocations.
*
* @param inPointer a pointer to the memory to deallocate.
*/
inline void operator delete( void *inPointer ) {
debugMemoryDelete( inPointer );
}
/**
* Overrides the delete [] operator to track memory allocations.
*
* @param inPointer a pointer to the memory to deallocate.
*/
inline void operator delete [] ( void *inPointer ) {
debugMemoryDeleteArray( inPointer );
}
#endif
// macro trickery to pass file name and line number into new
#ifdef DEBUG_MEMORY
#define DEBUG_NEW new( __FILE__, __LINE__ )
#else
#define DEBUG_NEW new
#endif
#define new DEBUG_NEW
#endif

View file

@ -0,0 +1,85 @@
/*
* Modification History
*
* 2002-October-17 Jason Rohrer
* Created.
*
* 2002-October-18 Jason Rohrer
* Added static initialization counting class for MemoryTrack.
*
* 2002-October-19 Jason Rohrer
* Removed call to debugMemoryPrintLeaksAndStopTracking.
* Made test cases more interesting.
* Added test cases for deleting NULL pointers.
*/
#include "minorGems/util/development/memory/debugMemory.h"
#include <stdio.h>
class TestClass {
public:
TestClass() {
mX = new int[5];
}
~TestClass() {
delete [] mX;
}
int *mX;
};
int main() {
int *x = new int[5];
printf( "array contents before initializing elements:\n"
"%d, %d, %d, %d, %d\n\n",
x[0], x[1], x[2], x[3], x[4] );
x[0] = 1;
x[1] = 2;
x[2] = 3;
x[3] = 4;
x[4] = 5;
printf( "array contents before deleting:\n"
"%d, %d, %d, %d, %d\n\n",
x[0], x[1], x[2], x[3], x[4] );
delete [] x;
printf( "array contents after deleting:\n"
"%d, %d, %d, %d, %d\n\n",
x[0], x[1], x[2], x[3], x[4] );
int *y = new int[4];
y[0] = 1;
TestClass *t = new TestClass();
delete t;
int *z = new int[7];
delete z;
//delete t;
int *badPointer = NULL;
delete badPointer;
int *badPointer2 = NULL;
delete [] badPointer2;
return 0;
}