Block size histogram added

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@5836 30fe4595-0a0c-4342-8851-515496e4dcbd
This commit is contained in:
wdbee 2014-11-14 21:58:42 +00:00
parent f72e862a70
commit f80314ab60
3 changed files with 152 additions and 57 deletions

View File

@ -4,7 +4,7 @@
created : Wed Nov 12 17:54:00:00 CEST 2014
copyright : (C) 2014 by Wolf-Dieter Beelitz
email : wdb at wdbee.de
version : $Id$
version : $Id:$
***************************************************************************/
/***************************************************************************
@ -29,7 +29,7 @@
#include <windows.h>
#include <crtdbg.h>
#include <assert.h>
#define GetRetAddrs void* retAddr = __builtin_return_address(0)
#define GetRetAddrs __builtin_return_address(0)
// ... MinGW
#else
// VC++ ...
@ -40,7 +40,7 @@
#include <intrin.h>
#pragma intrinsic(_ReturnAddress)
#undef ANSI_ISO // Old VC++ versions returning NULL instead of exception
#define GetRetAddrs void* retAddr = _ReturnAddress()
#define GetRetAddrs _ReturnAddress()
// ... VC++
#endif
// ... Windows
@ -73,9 +73,10 @@ static unsigned int GfMM_Counter = 0; // Counter of memory blocks
//============================================================================*
// API: Override the global new operator
//----------------------------------------------------------------------------*
//ExternC void* operator new (size_t size)
void* operator new (size_t size)
{
GetRetAddrs;
void* retAddr = GetRetAddrs;
return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_NEW,retAddr);
}
//============================================================================*
@ -83,7 +84,8 @@ void* operator new (size_t size)
//============================================================================*
// API: Override the global delete operator
//----------------------------------------------------------------------------*
void operator delete (void *b)
//ExternC void operator delete (void* b)
void operator delete (void* b)
{
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_NEW);
}
@ -92,9 +94,9 @@ void operator delete (void *b)
//============================================================================*
// API: Override malloc
//----------------------------------------------------------------------------*
void * _tgf_win_malloc(size_t size)
ExternC void* _tgf_win_malloc(size_t size)
{
GetRetAddrs;
void* retAddr = GetRetAddrs;
return GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
}
//============================================================================*
@ -102,7 +104,7 @@ void * _tgf_win_malloc(size_t size)
//============================================================================*
// API: Override free
//----------------------------------------------------------------------------*
void _tgf_win_free(void * b)
ExternC void _tgf_win_free(void* b)
{
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_MALLOC);
}
@ -111,10 +113,10 @@ void _tgf_win_free(void * b)
//============================================================================*
// API: Override calloc
//----------------------------------------------------------------------------*
void * _tgf_win_calloc(size_t num, size_t size)
ExternC void* _tgf_win_calloc(size_t num, size_t size)
{
GetRetAddrs;
void * p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
void* retAddr = GetRetAddrs;
void* p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
memset(p, 0, num * size);
return p;
}
@ -123,9 +125,9 @@ void * _tgf_win_calloc(size_t num, size_t size)
//============================================================================*
// API: Override recalloc
//----------------------------------------------------------------------------*
void * _tgf_win_realloc(void * memblock, size_t size)
ExternC void* _tgf_win_realloc(void* memblock, size_t size)
{
GetRetAddrs;
void* retAddr = GetRetAddrs;
if (size == 0)
{
@ -133,7 +135,7 @@ void * _tgf_win_realloc(void * memblock, size_t size)
return NULL;
}
void * p = GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
void* p = GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
if (p == NULL)
{
return NULL;
@ -143,9 +145,14 @@ void * _tgf_win_realloc(void * memblock, size_t size)
{
if (GfMemoryManagerRunning())
{
size_t s = MIN(*(int*)((char*)memblock
- sizeof(tDSMMLinkBlock) - sizeof(int)
- GfMM->AddedSpace), (int)size);
// Needed additional space
int bsize =
sizeof(tDSMMLinkBlock) // Data of Memory Manager
+ sizeof(int) // Requested size of the block
+ sizeof(int) // Marker to detect corrupted blocks
+ GfMM->AddedSpace; // Security margin for debugging
size_t s = MIN(*(int*)((char*) memblock - bsize), (int) size);
memcpy(p, memblock, s);
}
@ -166,9 +173,9 @@ void * _tgf_win_realloc(void * memblock, size_t size)
//============================================================================*
// API: Override strdup
//----------------------------------------------------------------------------*
char * _tgf_win_strdup(const char * str)
ExternC char * _tgf_win_strdup(const char * str)
{
GetRetAddrs;
void* retAddr = GetRetAddrs;
char * s = (char*) GfMemoryManagerAlloc(
strlen(str)+1,GF_MM_ALLOCTYPE_MALLOC,retAddr);
@ -190,7 +197,7 @@ char * _tgf_win_strdup(const char * str)
//============================================================================*
// Create the one and only global memory manager (allocate memory for data)
//----------------------------------------------------------------------------*
tMemoryManager* GfMemoryManager()
tMemoryManager* GfMemoryManager(void)
{
tMemoryManager* MemoryManager = (tMemoryManager*)
malloc(sizeof(tMemoryManager));
@ -209,6 +216,10 @@ tMemoryManager* GfMemoryManager()
MemoryManager->GarbageCollection = (tDSMMLinkBlock*) MemoryManager;
MemoryManager->BigB = 0;
for (int I = 0; I < MAXBLOCKSIZE; I++)
MemoryManager->Hist[I] = 0;
return MemoryManager;
}
//============================================================================*
@ -260,6 +271,9 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int type, void* retAddr)
c->IDMk = MM_MARKER_ID;
int ID = c->BLID = GfMM_Counter++;
// Update statistics
GfMemoryManagerHist(size);
// Get address to the marker at the end
char* e = (char*) c;
int* m = (int*) (e + bsize - sizeof(int));
@ -275,7 +289,7 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int type, void* retAddr)
// Now we have here
// s: (int*) pointer to the size of the allocated block
void* b = (void *) ++s;
void* b = (void*) ++s;
// Now we have here
// b: (void*) official pointer to the new data block
@ -313,7 +327,7 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int type, void* retAddr)
//============================================================================*
// Release memory
//----------------------------------------------------------------------------*
void GfMemoryManagerFree (void *b, unsigned int type)
void GfMemoryManagerFree (void* b, unsigned int type)
{
if (b == NULL) // If already done
return; // return without action
@ -323,12 +337,12 @@ void GfMemoryManagerFree (void *b, unsigned int type)
// Get start of data block ...
int* s = (int*) b;
tDSMMLinkBlock* c = (tDSMMLinkBlock*) --s;
c = --c;
--c;
// ... Get start of data block
// Now we have here
// b: (void*) official pointer to data block
// s: (in*) to size of allocated block
// s: (int*) to size of allocated block
// c: (tDSMMLinkBlock*) to the current linked list data block
// and will use
// n: (tDSMMLinkBlock*) to the next linked list data block
@ -416,7 +430,7 @@ void GfMemoryManagerSetup(int AddedSpace)
//============================================================================*
// Initialize the global memory manager
//----------------------------------------------------------------------------*
bool GfMemoryManagerAllocate()
bool GfMemoryManagerAllocate(void)
{
if (GfMM == NULL)
{
@ -439,7 +453,7 @@ bool GfMemoryManagerAllocate()
//============================================================================*
// Destroy the one and only global memory manager and it's allocated data
//----------------------------------------------------------------------------*
void GfMemoryManagerRelease()
void GfMemoryManagerRelease(void)
{
int LeakSizeTotal = 0;
int LeakSizeNewTotal = 0;
@ -452,6 +466,7 @@ void GfMemoryManagerRelease()
if (GfMM != NULL)
{
tDSMMLinkBlock* Block = GfMM->GarbageCollection;
tMemoryManager* MM = GfMM;
GfMM = NULL;
tDSMMLinkBlock* CurrentBlock = Block->Next;
@ -506,12 +521,33 @@ void GfMemoryManagerRelease()
fprintf(stderr,"Max leak block size new/delete : %d [Byte]\n",MaxLeakSizeNewTotal);
fprintf(stderr,"Max leak block size malloc/free: %d [Byte]\n",MaxLeakSizeMallocTotal);
fprintf(stderr,"Max leak block size total : %d [Byte]\n\n",MaxLeakSizeTotal);
fprintf(stderr,"Max leak block size total : %d [Byte]\n",MaxLeakSizeTotal);
unsigned int total = MM->Hist[0];
for (int I = 1; I < MAXBLOCKSIZE; I++)
total += I * MM->Hist[I];
total /= (1024 * 1024); // Byte -> MB
fprintf(stderr,"\nTotal size of blocks requested : %d [MB]\n",total);
fprintf(stderr,"\nNumber of blocks >= %d [Byte] : %d",MAXBLOCKSIZE,MM->BigB);
fprintf(stderr,"\nTotal size of blocks >= %d [Byte] : %.3f [kB]",MAXBLOCKSIZE,MM->Hist[0]/1024.0);
fprintf(stderr,"\nMean size of blocks >= %d [Byte] : %.3f [kB]\n",MAXBLOCKSIZE,MM->Hist[0]/1024.0 / MM->BigB);
fprintf(stderr,"\nHistogram of block sizes < %d [Byte]:\n",MAXBLOCKSIZE);
fprintf(stderr,"\nBlocksize : Number of blocks requested\n");
for (int I = 1; I < MAXBLOCKSIZE; I++)
{
if (MM->Hist[I] > 0)
fprintf(stderr,"%04.4d : %d\n",I,MM->Hist[I]);
}
delete(Block); // Delete the memory manager itself
}
fprintf(stderr,"Press [Enter] to close the program\n");
fprintf(stderr,"\nPress [Enter] to close the program\n");
getchar();
}
//============================================================================*
@ -519,7 +555,7 @@ void GfMemoryManagerRelease()
//============================================================================*
// Check for Memory Manager running
//----------------------------------------------------------------------------*
bool GfMemoryManagerRunning()
bool GfMemoryManagerRunning(void)
{
if (GfMM != NULL)
return true;
@ -531,7 +567,7 @@ bool GfMemoryManagerRunning()
//============================================================================*
// Set DoNotFree flag for debugging
//----------------------------------------------------------------------------*
void GfMemoryManagerDoAccept()
void GfMemoryManagerDoAccept(void)
{
GfMM->DoNotFree = true;
}
@ -540,11 +576,26 @@ void GfMemoryManagerDoAccept()
//============================================================================*
// Reset DoNotFree flag for debugging
//----------------------------------------------------------------------------*
void GfMemoryManagerDoFree()
void GfMemoryManagerDoFree(void)
{
GfMM->DoNotFree = false;
}
//============================================================================*
//============================================================================*
// Update statistics
//----------------------------------------------------------------------------*
void GfMemoryManagerHist(size_t size)
{
if (size < MAXBLOCKSIZE)
GfMM->Hist[size] += 1;
else
{
GfMM->BigB += 1;
GfMM->Hist[0] += size;
}
}
//============================================================================*
//----------------------------------------------------------------------------*
// ... Implementation

View File

@ -28,12 +28,12 @@
//
// Interface
//
TGF_API bool GfMemoryManagerAllocate(); // Initialize memory manager
TGF_API void GfMemoryManagerRelease(); // Release memory manager at Shutdown
TGF_API bool GfMemoryManagerRunning(); // Is the memory manager running?
TGF_API bool GfMemoryManagerAllocate(void); // Initialize memory manager
TGF_API void GfMemoryManagerRelease(void); // Release memory manager at Shutdown
TGF_API bool GfMemoryManagerRunning(void); // Is the memory manager running?
TGF_API void GfMemoryManagerSetup(int AddedSpace);
TGF_API void GfMemoryManagerDoAccept();
TGF_API void GfMemoryManagerDoFree();
TGF_API void GfMemoryManagerDoAccept(void);
TGF_API void GfMemoryManagerDoFree(void);
//
//
@ -45,25 +45,30 @@ TGF_API void GfMemoryManagerDoFree();
#define GF_MM_STATE_INIT 1 // memory manager was initialized
#define GF_MM_STATE_USED 2 // memory manager was used
// Memory manager allocation types
#define GF_MM_ALLOCTYPE_MEMMAN 0 // allocation for memory manager
#define GF_MM_ALLOCTYPE_NEW 1 // allocation by new
#define GF_MM_ALLOCTYPE_NEWARRAY 2 // allocation by new
#define GF_MM_ALLOCTYPE_MALLOC 3 // allocation by calloc
#define MM_MARKER_BEGIN 11223344
#define MM_MARKER_ID 123456789
#define MM_MARKER_END 44332211
// Memory manager check markers
#define MM_MARKER_BEGIN 11223344 // Value of marker at start of the block
#define MM_MARKER_ID 123456789 // Value of marker in front of the ID
#define MM_MARKER_END 44332211 // Value of marker at the end of the block
// Memory manager histogram
#define MAXBLOCKSIZE 4096 // Definition of the max block size for histogram
//
// Memory manager worker functions
void* GfMemoryManagerAlloc(size_t size, unsigned int type, void* RetAddr);
void* GfMemoryManagerAlloc(size_t size, unsigned int type, void* retAddr);
void GfMemoryManagerFree(void* b, unsigned int type);
void GfMemoryManagerAccept(void* b, unsigned int type);
void GfMemoryManagerHist(size_t size);
//
// Block to link allocated memory blocks in a
// double linked list.
//
// double linked list and some additional flags to check
// integrity of block at call of free
typedef struct tDSMMLinkBlock
{
unsigned int Mark; // Marker to identify it as tDSMMLinkBlock
@ -89,6 +94,9 @@ typedef struct
int AddedSpace; // Number of bytes added to each block
bool DoNotFree; // Do not free the blocks if flag is set
unsigned int BigB; // Number of big blocks requested
unsigned int Hist[MAXBLOCKSIZE]; // Histogram of the buufer sizes
} tMemoryManager;
//

View File

@ -212,14 +212,41 @@ TGF_API void GfPoolMove(tMemoryPool* oldPool, tMemoryPool* newPool);
// <esppat>
//#define TGF_ALLOC_DEBUG 1
//#if (defined(WIN32) && defined(TGF_ALLOC_DEBUG))
// </esppat>
/*********************************
* New memory debug tools *
*********************************/
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
// New Memory Manager ...
//----------------------------------------------------------------------------*
//============================================================================*
// Configuration for the new Memory Manager
//----------------------------------------------------------------------------*
// To enable the hunting for memory leaks uncomment the following line
//#define __DEBUG_MEMORYMANAGER__
#if (defined(WIN32) && defined(__DEBUG_MEMORYMANAGER__))
#if defined(__DEBUG_MEMORYMANAGER__)
// Use new Memory Manager ...
#if defined(WIN32)
// Windows ...
#if defined(__MINGW32__)
// MinGW ...
#define ExternC extern "C"
// ... MinGW
#else
// VC++ ...
#define ExternC
// ... VC++
#endif
// ... Windows
#else
// Linux ...
// ... Linux
#endif
//============================================================================*
//============================================================================*
// Definitions of the replacements for the new Memory Manager
//----------------------------------------------------------------------------*
#define malloc _tgf_win_malloc
#define calloc _tgf_win_calloc
#define realloc _tgf_win_realloc
@ -232,17 +259,26 @@ TGF_API void GfPoolMove(tMemoryPool* oldPool, tMemoryPool* newPool);
#endif
#define strdup _tgf_win_strdup
#define _strdup _tgf_win_strdup
TGF_API void * _tgf_win_malloc(size_t size);
TGF_API void * _tgf_win_calloc(size_t num, size_t size);
TGF_API void * _tgf_win_realloc(void * memblock, size_t size);
TGF_API void _tgf_win_free(void * memblock);
TGF_API void _tgf_win_accept(void * memblock);
TGF_API char * _tgf_win_strdup(const char * str);
TGF_API void GfMemoryManagerDoAccept();
TGF_API void GfMemoryManagerDoFree();
//============================================================================*
#endif // WIN32
// </esppat>
//============================================================================*
// Prototypes of the replacement functions for the new Memory Manager
//----------------------------------------------------------------------------*
ExternC TGF_API void* _tgf_win_malloc(size_t size);
ExternC TGF_API void* _tgf_win_calloc(size_t num, size_t size);
ExternC TGF_API void* _tgf_win_realloc(void * memblock, size_t size);
ExternC TGF_API void _tgf_win_free(void * memblock);
ExternC TGF_API void _tgf_win_accept(void * memblock);
ExternC TGF_API char* _tgf_win_strdup(const char * str);
ExternC TGF_API void GfMemoryManagerDoAccept();
ExternC TGF_API void GfMemoryManagerDoFree();
//============================================================================*
// ... Use new Memroy Manager
#endif // #if defined(__DEBUG_MEMORYMANAGER__))
//----------------------------------------------------------------------------*
// ... New Memory Manager
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
/*********************************