forked from speed-dreams/speed-dreams-code
Code cleanup Memory Manager
Increased readability Dump formated to be usable as csv for spreadsheets (sorting by IDs and adresses) Found the reason for the corrupted blocks -> freed twice Extended registration for screens to avoid the issues Prepared port for MinGW git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@5835 30fe4595-0a0c-4342-8851-515496e4dcbd Former-commit-id: b192f6c2c2af9da070a8f64bf5f0dc6013e55cb2 Former-commit-id: 5c364044e8d0292787f5951804115f16b8d695be
This commit is contained in:
parent
3d99d4edf3
commit
8a18586843
7 changed files with 269 additions and 202 deletions
|
@ -4,7 +4,7 @@
|
||||||
created : Wed Nov 12 17:54:00:00 CEST 2014
|
created : Wed Nov 12 17:54:00:00 CEST 2014
|
||||||
copyright : (C) 2014 by Wolf-Dieter Beelitz
|
copyright : (C) 2014 by Wolf-Dieter Beelitz
|
||||||
email : wdb at wdbee.de
|
email : wdb at wdbee.de
|
||||||
version : $Id: memmanager.cpp $
|
version : $Id$
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -16,119 +16,126 @@
|
||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
// WDB test ...
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#include <unistd.h> // getcwd, access
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "memmanager.h"
|
#include "memmanager.h"
|
||||||
#ifdef __DEBUG_MEMORYMANAGER__
|
#ifdef __DEBUG_MEMORYMANAGER__
|
||||||
|
|
||||||
#if defined(__MINGW32__)
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||||
|
// Configuration ...
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
|
#ifdef WIN32
|
||||||
|
// Windows ...
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
// MinGW ...
|
||||||
|
#include <windows.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#define GetRetAddrs void* retAddr = __builtin_return_address(0)
|
||||||
|
// ... MinGW
|
||||||
|
#else
|
||||||
|
// VC++ ...
|
||||||
|
#include <windows.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <intrin.h>
|
||||||
|
#pragma intrinsic(_ReturnAddress)
|
||||||
|
#undef ANSI_ISO // Old VC++ versions returning NULL instead of exception
|
||||||
|
#define GetRetAddrs void* retAddr = _ReturnAddress()
|
||||||
|
// ... VC++
|
||||||
|
#endif
|
||||||
|
// ... Windows
|
||||||
#else
|
#else
|
||||||
#include <stdio.h>
|
// Linux ...
|
||||||
#include <intrin.h>
|
#include <unistd.h> // getcwd, access
|
||||||
|
#define ANSI_ISO // ANSI/ISO compliant behavior: exeption if allo failed
|
||||||
#pragma intrinsic(_ReturnAddress)
|
// ... Linux
|
||||||
#endif
|
#endif
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
|
// ... Configuration
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||||
|
|
||||||
//
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||||
// Configuration (depending on the compiler)
|
// Implementation ...
|
||||||
//
|
|
||||||
//#define ANSI_ISO // ANSI/ISO compliant behavior: exeption if allo failed
|
|
||||||
#undef ANSI_ISO // Older Visual C++ versions returning NULL instad of exception
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Private variables
|
// Private variables
|
||||||
//
|
//
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
static tMemoryManager* GfMM = NULL; // The one and only memory manager!
|
static tMemoryManager* GfMM = NULL; // The one and only memory manager!
|
||||||
static unsigned int GfMM_Counter = 0; // Counter of memory blocks
|
static unsigned int GfMM_Counter = 0; // Counter of memory blocks
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
|
// ... Implementation
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||||
|
|
||||||
//
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||||
// Override the global new operator
|
// Interface ...
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
|
|
||||||
|
//============================================================================*
|
||||||
|
// API: Override the global new operator
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
void* operator new (size_t size)
|
void* operator new (size_t size)
|
||||||
{
|
{
|
||||||
#if defined(__MINGW32__)
|
GetRetAddrs;
|
||||||
void* RetAddr = __builtin_return_address (0); // gcc
|
return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_NEW,retAddr);
|
||||||
#else
|
|
||||||
void* RetAddr = _ReturnAddress(); // VC++
|
|
||||||
#endif
|
|
||||||
return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_NEW,RetAddr);
|
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Override the global delete operator
|
// API: Override the global delete operator
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
void operator delete (void *b)
|
void operator delete (void *b)
|
||||||
{
|
{
|
||||||
if (GfMemoryManagerRunning())
|
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_NEW);
|
||||||
{
|
|
||||||
if (GfMM->DoNotFree)
|
|
||||||
GfMemoryManagerAccept(b, GF_MM_ALLOCTYPE_NEW);
|
|
||||||
else
|
|
||||||
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_NEW);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_NEW);
|
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
#if defined(WIN32)
|
|
||||||
|
|
||||||
#include <crtdbg.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
|
//============================================================================*
|
||||||
|
// API: Override malloc
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
void * _tgf_win_malloc(size_t size)
|
void * _tgf_win_malloc(size_t size)
|
||||||
{
|
{
|
||||||
#if defined(__MINGW32__)
|
GetRetAddrs;
|
||||||
void* RetAddr = __builtin_return_address (0); // gcc
|
return GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||||
#else
|
|
||||||
void* RetAddr = _ReturnAddress(); // VC++
|
|
||||||
#endif
|
|
||||||
return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_MALLOC,RetAddr);
|
|
||||||
}
|
}
|
||||||
|
//============================================================================*
|
||||||
|
|
||||||
|
//============================================================================*
|
||||||
|
// API: Override free
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
void _tgf_win_free(void * b)
|
void _tgf_win_free(void * b)
|
||||||
{
|
{
|
||||||
if (GfMemoryManagerRunning())
|
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_MALLOC);
|
||||||
{
|
|
||||||
if (GfMM->DoNotFree)
|
|
||||||
GfMemoryManagerAccept(b, GF_MM_ALLOCTYPE_MALLOC);
|
|
||||||
else
|
|
||||||
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_MALLOC);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_MALLOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _tgf_win_accept(void * b)
|
|
||||||
{
|
|
||||||
GfMemoryManagerAccept(b, GF_MM_ALLOCTYPE_MALLOC);
|
|
||||||
}
|
}
|
||||||
|
//============================================================================*
|
||||||
|
|
||||||
|
//============================================================================*
|
||||||
|
// API: Override calloc
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
void * _tgf_win_calloc(size_t num, size_t size)
|
void * _tgf_win_calloc(size_t num, size_t size)
|
||||||
{
|
{
|
||||||
void * p = _tgf_win_malloc(num * size);
|
GetRetAddrs;
|
||||||
|
void * p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||||
memset(p, 0, num * size);
|
memset(p, 0, num * size);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
//============================================================================*
|
||||||
|
|
||||||
|
//============================================================================*
|
||||||
|
// API: Override recalloc
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
void * _tgf_win_realloc(void * memblock, size_t size)
|
void * _tgf_win_realloc(void * memblock, size_t size)
|
||||||
{
|
{
|
||||||
if (size == 0) {
|
GetRetAddrs;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
_tgf_win_free(memblock);
|
_tgf_win_free(memblock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * p = _tgf_win_malloc(size);
|
void * p = GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||||
if (p == NULL) {
|
if (p == NULL)
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,12 +143,17 @@ void * _tgf_win_realloc(void * memblock, size_t size)
|
||||||
{
|
{
|
||||||
if (GfMemoryManagerRunning())
|
if (GfMemoryManagerRunning())
|
||||||
{
|
{
|
||||||
size_t s = MIN(*(int*)((char*)memblock - sizeof(tDSMMLinkBlock) - sizeof(int) - GfMM->AddedSpace), (int)size);
|
size_t s = MIN(*(int*)((char*)memblock
|
||||||
|
- sizeof(tDSMMLinkBlock) - sizeof(int)
|
||||||
|
- GfMM->AddedSpace), (int)size);
|
||||||
|
|
||||||
memcpy(p, memblock, s);
|
memcpy(p, memblock, s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t s = MIN(*(int*)((char*)memblock - sizeof(int)), (int)size);
|
size_t s = MIN(*(int*)((char*)memblock
|
||||||
|
- sizeof(int)), (int)size);
|
||||||
|
|
||||||
memcpy(p, memblock, s);
|
memcpy(p, memblock, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,21 +161,35 @@ void * _tgf_win_realloc(void * memblock, size_t size)
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
//============================================================================*
|
||||||
|
|
||||||
|
//============================================================================*
|
||||||
|
// API: Override strdup
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
char * _tgf_win_strdup(const char * str)
|
char * _tgf_win_strdup(const char * str)
|
||||||
{
|
{
|
||||||
char * s = (char*)_tgf_win_malloc(strlen(str)+1);
|
GetRetAddrs;
|
||||||
|
|
||||||
|
char * s = (char*) GfMemoryManagerAlloc(
|
||||||
|
strlen(str)+1,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||||
|
|
||||||
strcpy(s,str);
|
strcpy(s,str);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
#endif // if defined(WIN32)
|
//============================================================================*
|
||||||
//
|
|
||||||
|
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
|
// ... Interface
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||||
|
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||||
|
// Implementation ...
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
|
|
||||||
|
//============================================================================*
|
||||||
// Create the one and only global memory manager (allocate memory for data)
|
// Create the one and only global memory manager (allocate memory for data)
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
tMemoryManager* GfMemoryManager()
|
tMemoryManager* GfMemoryManager()
|
||||||
{
|
{
|
||||||
tMemoryManager* MemoryManager = (tMemoryManager*)
|
tMemoryManager* MemoryManager = (tMemoryManager*)
|
||||||
|
@ -174,36 +200,46 @@ tMemoryManager* GfMemoryManager()
|
||||||
MemoryManager->AddedSpace = 0;
|
MemoryManager->AddedSpace = 0;
|
||||||
MemoryManager->DoNotFree = false;
|
MemoryManager->DoNotFree = false;
|
||||||
|
|
||||||
MemoryManager->RootOfList.Mark = MM_MARKER;
|
MemoryManager->RootOfList.Mark = MM_MARKER_BEGIN;
|
||||||
MemoryManager->RootOfList.Type = GF_MM_ALLOCTYPE_MEMMAN;
|
MemoryManager->RootOfList.Type = GF_MM_ALLOCTYPE_MEMMAN;
|
||||||
MemoryManager->RootOfList.Prev = NULL;
|
MemoryManager->RootOfList.Prev = NULL;
|
||||||
MemoryManager->RootOfList.Next = NULL;
|
MemoryManager->RootOfList.Next = NULL;
|
||||||
MemoryManager->RootOfList.Size = sizeof(tMemoryManager);
|
MemoryManager->RootOfList.Size = sizeof(tMemoryManager);
|
||||||
MemoryManager->RootOfList.ID = GfMM_Counter++;
|
MemoryManager->RootOfList.BLID = GfMM_Counter++;
|
||||||
|
|
||||||
MemoryManager->GarbageCollection = (tDSMMLinkBlock*) MemoryManager;
|
MemoryManager->GarbageCollection = (tDSMMLinkBlock*) MemoryManager;
|
||||||
|
|
||||||
return MemoryManager;
|
return MemoryManager;
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Allocate memory
|
// Allocate memory
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
void* GfMemoryManagerAlloc (size_t size, unsigned int Type, void* RetAddr)
|
void* GfMemoryManagerAlloc (size_t size, unsigned int type, void* retAddr)
|
||||||
{
|
{
|
||||||
if (GfMemoryManagerRunning())
|
if (GfMemoryManagerRunning())
|
||||||
{
|
{
|
||||||
// Need additional space for linked list
|
// Need additional space for linked list and other data
|
||||||
int blocksize = sizeof(tDSMMLinkBlock) + sizeof(int) + size + GfMM->AddedSpace;
|
int bsize =
|
||||||
tDSMMLinkBlock* c = (tDSMMLinkBlock*) GlobalAlloc(GMEM_FIXED, blocksize);
|
sizeof(tDSMMLinkBlock) // Data of Memory Manager
|
||||||
if (c == NULL) // did malloc succeed?
|
+ sizeof(int) // Requested size of the block
|
||||||
|
+ size // Space allocated for caller
|
||||||
|
+ sizeof(int) // Marker to detect corrupted blocks
|
||||||
|
+ GfMM->AddedSpace; // Security margin for debugging
|
||||||
|
|
||||||
|
// Allocate memory block
|
||||||
|
tDSMMLinkBlock* c = (tDSMMLinkBlock*) GlobalAlloc(GMEM_FIXED, bsize);
|
||||||
|
|
||||||
|
// Check pointer to the block
|
||||||
|
if (c == NULL)
|
||||||
#ifdef ANSI_ISO
|
#ifdef ANSI_ISO
|
||||||
throw std::bad_alloc(); // ANSI/ISO compliant behavior
|
throw std::bad_alloc(); // ANSI/ISO compliant behavior
|
||||||
#else
|
#else
|
||||||
return c;
|
return c;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Put block into the double linked list
|
||||||
if (GfMM->RootOfList.Next != NULL)
|
if (GfMM->RootOfList.Next != NULL)
|
||||||
{
|
{
|
||||||
tDSMMLinkBlock* n = GfMM->RootOfList.Next;
|
tDSMMLinkBlock* n = GfMM->RootOfList.Next;
|
||||||
|
@ -211,16 +247,23 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int Type, void* RetAddr)
|
||||||
c->Next = n;
|
c->Next = n;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
c->Next = NULL;
|
c->Next = NULL; // Is last block
|
||||||
|
|
||||||
GfMM->RootOfList.Next = c;
|
GfMM->RootOfList.Next = c;
|
||||||
c->Prev = &GfMM->RootOfList;
|
c->Prev = &GfMM->RootOfList;
|
||||||
|
|
||||||
c->Mark = MM_MARKER;
|
// Setup block data
|
||||||
c->Type = Type;
|
c->Mark = MM_MARKER_BEGIN;
|
||||||
|
c->Type = type;
|
||||||
c->Size = size;
|
c->Size = size;
|
||||||
c->ReturnAddress = RetAddr;
|
c->RAdr = retAddr;
|
||||||
int ID = c->ID = GfMM_Counter++;
|
c->IDMk = MM_MARKER_ID;
|
||||||
|
int ID = c->BLID = GfMM_Counter++;
|
||||||
|
|
||||||
|
// Get address to the marker at the end
|
||||||
|
char* e = (char*) c;
|
||||||
|
int* m = (int*) (e + bsize - sizeof(int));
|
||||||
|
*m = MM_MARKER_END;
|
||||||
|
|
||||||
// Now we have here
|
// Now we have here
|
||||||
// c: tDSMMLinkBlock* to the current linked list data block
|
// c: tDSMMLinkBlock* to the current linked list data block
|
||||||
|
@ -238,7 +281,7 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int Type, void* RetAddr)
|
||||||
// b: (void*) official pointer to the new data block
|
// b: (void*) official pointer to the new data block
|
||||||
|
|
||||||
// Hunting memory leaks ...
|
// Hunting memory leaks ...
|
||||||
#define IDTOSTOP 343884 // ID of block you are looking for
|
#define IDTOSTOP 371835 // ID of block you are looking for
|
||||||
|
|
||||||
if (ID == IDTOSTOP)
|
if (ID == IDTOSTOP)
|
||||||
{
|
{
|
||||||
|
@ -265,15 +308,15 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int Type, void* RetAddr)
|
||||||
return ++b;
|
return ++b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Release memory
|
// Release memory
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
void GfMemoryManagerFree (void *b, unsigned int type)
|
void GfMemoryManagerFree (void *b, unsigned int type)
|
||||||
{
|
{
|
||||||
if (b == NULL)
|
if (b == NULL) // If already done
|
||||||
return;
|
return; // return without action
|
||||||
|
|
||||||
if (GfMemoryManagerRunning())
|
if (GfMemoryManagerRunning())
|
||||||
{
|
{
|
||||||
|
@ -287,85 +330,75 @@ void GfMemoryManagerFree (void *b, unsigned int type)
|
||||||
// b: (void*) official pointer to data block
|
// b: (void*) official pointer to data block
|
||||||
// s: (in*) to size of allocated block
|
// s: (in*) to size of allocated block
|
||||||
// c: (tDSMMLinkBlock*) to the current linked list data block
|
// c: (tDSMMLinkBlock*) to the current linked list data block
|
||||||
|
// and will use
|
||||||
// n: (tDSMMLinkBlock*) to the next linked list data block
|
// n: (tDSMMLinkBlock*) to the next linked list data block
|
||||||
// p: (tDSMMLinkBlock*) to the previous linked list data block
|
// p: (tDSMMLinkBlock*) to the previous linked list data block
|
||||||
|
|
||||||
if (c->Type != type)
|
// Get address to the marker at the end
|
||||||
|
// Need additional space for linked list and other data
|
||||||
|
int bsize =
|
||||||
|
sizeof(tDSMMLinkBlock) // Data of Memory Manager
|
||||||
|
+ sizeof(int) // Requested size of the block
|
||||||
|
+ c->Size // Space allocated for caller
|
||||||
|
+ sizeof(int) // Marker to detect corrupted blocks
|
||||||
|
+ GfMM->AddedSpace; // Security margin for debugging
|
||||||
|
|
||||||
|
char* e = (char*) c;
|
||||||
|
int* m = (int*) (e + bsize - sizeof(int));
|
||||||
|
|
||||||
|
// Check block
|
||||||
|
if ((c->Mark != MM_MARKER_BEGIN) || (*m != MM_MARKER_END))
|
||||||
{
|
{
|
||||||
fprintf(stderr,"Block address %p\n",c);
|
// Block is corrupted
|
||||||
if (c->Mark == MM_MARKER)
|
if (c->IDMk != MM_MARKER_ID)
|
||||||
fprintf(stderr,"operator delete called with data of wrong type\n");
|
fprintf(stderr,
|
||||||
|
"Called for corrupted block; %p;\n",c);
|
||||||
else
|
else
|
||||||
fprintf(stderr,"operator delete wrong data\n");
|
fprintf(stderr,
|
||||||
|
"Called for corrupted block; %d; at; %p;\n",c->BLID,c);
|
||||||
|
|
||||||
|
// Hunting corrupted blocks ...
|
||||||
|
if (c->BLID == IDTOSTOP)
|
||||||
|
{
|
||||||
|
c->BLID = 0; // set breakpoint here
|
||||||
|
}
|
||||||
|
// ... Hunting corrupted blocks
|
||||||
|
}
|
||||||
|
// Check call type (new/delete or malloc/free)
|
||||||
|
else if (c->Type != type)
|
||||||
|
{ // Show error message if new/free or malloc/delete
|
||||||
|
fprintf(stderr,
|
||||||
|
"Called by wrong call type for block; %d; at address; %p; (%d)\n",
|
||||||
|
c->BLID,c,c->Type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{ // Take the block out of the double linked list
|
||||||
tDSMMLinkBlock* n = c->Next;
|
tDSMMLinkBlock* n = c->Next;
|
||||||
tDSMMLinkBlock* p = c->Prev;
|
tDSMMLinkBlock* p = c->Prev;
|
||||||
if (c->Mark == MM_MARKER)
|
p->Next = n;
|
||||||
{
|
if ((n != NULL) && (n->Mark == MM_MARKER_BEGIN))
|
||||||
p->Next = n;
|
n->Prev = p;
|
||||||
if ((n != NULL) && (n->Mark == MM_MARKER))
|
|
||||||
n->Prev = p;
|
// Check release mode
|
||||||
GlobalFree(c);
|
if (GfMM->DoNotFree)
|
||||||
}
|
return; // accept the leak for debugging
|
||||||
|
|
||||||
|
// Release the allocated memory
|
||||||
|
GlobalFree(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
GlobalFree(b);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Accept memory
|
|
||||||
//
|
|
||||||
void GfMemoryManagerAccept (void *b, unsigned int type)
|
|
||||||
{
|
|
||||||
if (b == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (GfMemoryManagerRunning())
|
|
||||||
{
|
{
|
||||||
// Get start of data block ...
|
// Handle blocks that are allocated without the Memory Manager
|
||||||
int* s = (int*) b;
|
// or stayed in the list while release the Memory Manager
|
||||||
tDSMMLinkBlock* c = (tDSMMLinkBlock*) --s;
|
GlobalFree(b);
|
||||||
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
|
|
||||||
// c: (tDSMMLinkBlock*) to the current linked list data block
|
|
||||||
// n: (tDSMMLinkBlock*) to the next linked list data block
|
|
||||||
// p: (tDSMMLinkBlock*) to the previous linked list data block
|
|
||||||
|
|
||||||
if (c->Type != type)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Block address %p\n",c);
|
|
||||||
if (c->Mark == MM_MARKER)
|
|
||||||
fprintf(stderr,"operator delete called with data of wrong type\n");
|
|
||||||
else
|
|
||||||
fprintf(stderr,"operator delete wrong data\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tDSMMLinkBlock* n = c->Next;
|
|
||||||
tDSMMLinkBlock* p = c->Prev;
|
|
||||||
if (c->Mark == MM_MARKER)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"accept block %d\n",c->ID);
|
|
||||||
p->Next = n;
|
|
||||||
if ((n != NULL) && (n->Mark == MM_MARKER))
|
|
||||||
n->Prev = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Setup data of memory manager
|
// Setup data of memory manager
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
void GfMemoryManagerSetup(int AddedSpace)
|
void GfMemoryManagerSetup(int AddedSpace)
|
||||||
{
|
{
|
||||||
if (GfMM != NULL)
|
if (GfMM != NULL)
|
||||||
|
@ -378,11 +411,11 @@ void GfMemoryManagerSetup(int AddedSpace)
|
||||||
GfMM->State = GF_MM_STATE_INIT;
|
GfMM->State = GF_MM_STATE_INIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Initialize the global memory manager
|
// Initialize the global memory manager
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
bool GfMemoryManagerAllocate()
|
bool GfMemoryManagerAllocate()
|
||||||
{
|
{
|
||||||
if (GfMM == NULL)
|
if (GfMM == NULL)
|
||||||
|
@ -401,11 +434,11 @@ bool GfMemoryManagerAllocate()
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Destroy the one and only global memory manager and it's allocated data
|
// Destroy the one and only global memory manager and it's allocated data
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
void GfMemoryManagerRelease()
|
void GfMemoryManagerRelease()
|
||||||
{
|
{
|
||||||
int LeakSizeTotal = 0;
|
int LeakSizeTotal = 0;
|
||||||
|
@ -429,7 +462,7 @@ void GfMemoryManagerRelease()
|
||||||
tDSMMLinkBlock* ToFree = CurrentBlock;
|
tDSMMLinkBlock* ToFree = CurrentBlock;
|
||||||
CurrentBlock = CurrentBlock->Next;
|
CurrentBlock = CurrentBlock->Next;
|
||||||
|
|
||||||
if (ToFree->Mark == MM_MARKER)
|
if (ToFree->Mark == MM_MARKER_BEGIN)
|
||||||
{
|
{
|
||||||
LeakSizeTotal += ToFree->Size;
|
LeakSizeTotal += ToFree->Size;
|
||||||
if (MaxLeakSizeTotal < ToFree->Size)
|
if (MaxLeakSizeTotal < ToFree->Size)
|
||||||
|
@ -437,8 +470,9 @@ void GfMemoryManagerRelease()
|
||||||
|
|
||||||
if (ToFree->Type == 1)
|
if (ToFree->Type == 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"%04.4d Block: %04.4d Size: %06.6d ReturnAddress: %p BlockAddress: %p Type: new/delete\n",
|
fprintf(stderr,
|
||||||
++n,ToFree->ID,ToFree->Size,ToFree->ReturnAddress,ToFree);
|
"%04.4d; Block; %04.4d; Size; %06.6d; ReturnTo; %p; Address; %p; new/delete;\n",
|
||||||
|
++n,ToFree->BLID,ToFree->Size,ToFree->RAdr,ToFree);
|
||||||
LeakSizeNewTotal += ToFree->Size;
|
LeakSizeNewTotal += ToFree->Size;
|
||||||
if (MaxLeakSizeNewTotal < ToFree->Size)
|
if (MaxLeakSizeNewTotal < ToFree->Size)
|
||||||
MaxLeakSizeNewTotal = ToFree->Size;
|
MaxLeakSizeNewTotal = ToFree->Size;
|
||||||
|
@ -446,8 +480,8 @@ void GfMemoryManagerRelease()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr,"%04.4d Block: %04.4d Size: %06.6d ReturnAddress: %p BlockAddress: %p Type: malloc/free\n",
|
fprintf(stderr,"%04.4d; Block; %04.4d; Size; %06.6d; ReturnTo; %p; Address; %p; malloc/free;\n",
|
||||||
++n,ToFree->ID,ToFree->Size,ToFree->ReturnAddress,ToFree);
|
++n,ToFree->BLID,ToFree->Size,ToFree->RAdr,ToFree);
|
||||||
LeakSizeMallocTotal += ToFree->Size;
|
LeakSizeMallocTotal += ToFree->Size;
|
||||||
if (MaxLeakSizeMallocTotal < ToFree->Size)
|
if (MaxLeakSizeMallocTotal < ToFree->Size)
|
||||||
MaxLeakSizeMallocTotal = ToFree->Size;
|
MaxLeakSizeMallocTotal = ToFree->Size;
|
||||||
|
@ -480,11 +514,11 @@ void GfMemoryManagerRelease()
|
||||||
fprintf(stderr,"Press [Enter] to close the program\n");
|
fprintf(stderr,"Press [Enter] to close the program\n");
|
||||||
getchar();
|
getchar();
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Check memory manager
|
// Check for Memory Manager running
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
bool GfMemoryManagerRunning()
|
bool GfMemoryManagerRunning()
|
||||||
{
|
{
|
||||||
if (GfMM != NULL)
|
if (GfMM != NULL)
|
||||||
|
@ -492,25 +526,29 @@ bool GfMemoryManagerRunning()
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Set DoNotFree flag for debugging
|
// Set DoNotFree flag for debugging
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
void GfMemoryManagerDoAccept()
|
void GfMemoryManagerDoAccept()
|
||||||
{
|
{
|
||||||
GfMM->DoNotFree = true;
|
GfMM->DoNotFree = true;
|
||||||
}
|
}
|
||||||
//
|
//============================================================================*
|
||||||
|
|
||||||
//
|
//============================================================================*
|
||||||
// Set DoNotFree flag for debugging
|
// Reset DoNotFree flag for debugging
|
||||||
//
|
//----------------------------------------------------------------------------*
|
||||||
void GfMemoryManagerDoFree()
|
void GfMemoryManagerDoFree()
|
||||||
{
|
{
|
||||||
GfMM->DoNotFree = false;
|
GfMM->DoNotFree = false;
|
||||||
}
|
}
|
||||||
|
//============================================================================*
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------*
|
||||||
|
// ... Implementation
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||||
#endif
|
#endif
|
||||||
// ... WDB test
|
// ... WDB test
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
created : Wed Nov 12 17:54:00:00 CEST 2014
|
created : Wed Nov 12 17:54:00:00 CEST 2014
|
||||||
copyright : (C) 2014 by Wolf-Dieter Beelitz
|
copyright : (C) 2014 by Wolf-Dieter Beelitz
|
||||||
email : wdb at wdbee.de
|
email : wdb at wdbee.de
|
||||||
version : $Id: memmanager.h $
|
version : $Id$
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -50,7 +50,9 @@ TGF_API void GfMemoryManagerDoFree();
|
||||||
#define GF_MM_ALLOCTYPE_NEWARRAY 2 // allocation by new
|
#define GF_MM_ALLOCTYPE_NEWARRAY 2 // allocation by new
|
||||||
#define GF_MM_ALLOCTYPE_MALLOC 3 // allocation by calloc
|
#define GF_MM_ALLOCTYPE_MALLOC 3 // allocation by calloc
|
||||||
|
|
||||||
#define MM_MARKER 11223344
|
#define MM_MARKER_BEGIN 11223344
|
||||||
|
#define MM_MARKER_ID 123456789
|
||||||
|
#define MM_MARKER_END 44332211
|
||||||
//
|
//
|
||||||
|
|
||||||
// Memory manager worker functions
|
// Memory manager worker functions
|
||||||
|
@ -66,11 +68,12 @@ typedef struct tDSMMLinkBlock
|
||||||
{
|
{
|
||||||
unsigned int Mark; // Marker to identify it as tDSMMLinkBlock
|
unsigned int Mark; // Marker to identify it as tDSMMLinkBlock
|
||||||
int Size; // Size of allocated block
|
int Size; // Size of allocated block
|
||||||
void* ReturnAddress; // Return address of new/malloc
|
void* RAdr; // Return address of new/malloc
|
||||||
tDSMMLinkBlock* Prev; // Previous memory block
|
tDSMMLinkBlock* Prev; // Previous memory block
|
||||||
tDSMMLinkBlock* Next; // Next memory block
|
tDSMMLinkBlock* Next; // Next memory block
|
||||||
unsigned int Type; // Type of allocation
|
unsigned int Type; // Type of allocation
|
||||||
unsigned int ID; // ID of allocated memory block
|
unsigned int IDMk; // Marker to check ID is still valid
|
||||||
|
unsigned int BLID; // ID of allocated memory block
|
||||||
|
|
||||||
} tDSMMLinkBlock;
|
} tDSMMLinkBlock;
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ GfModule::GfModule(const std::string& strShLibName, void* hShLibHandle)
|
||||||
|
|
||||||
GfModule::~GfModule()
|
GfModule::~GfModule()
|
||||||
{
|
{
|
||||||
|
_mapModulesByLibName.clear(); // Avoid memory leaks
|
||||||
}
|
}
|
||||||
|
|
||||||
GfModule* GfModule::load(const std::string& strShLibName)
|
GfModule* GfModule::load(const std::string& strShLibName)
|
||||||
|
|
|
@ -645,7 +645,7 @@ GfuiScreenReplace(void *screen)
|
||||||
tGfuiScreen *oldScreen = GfuiScreen;
|
tGfuiScreen *oldScreen = GfuiScreen;
|
||||||
|
|
||||||
if (oldScreen)
|
if (oldScreen)
|
||||||
GfuiScreenRelease(oldScreen);
|
// GfuiScreenRelease(oldScreen);
|
||||||
GfuiScreenActivate(screen);
|
GfuiScreenActivate(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,6 +724,8 @@ GfuiScreenRelease(void *scr)
|
||||||
tGfuiKey *nextKey;
|
tGfuiKey *nextKey;
|
||||||
tGfuiScreen *screen = (tGfuiScreen*)scr;
|
tGfuiScreen *screen = (tGfuiScreen*)scr;
|
||||||
|
|
||||||
|
UnregisterScreens(screen);
|
||||||
|
|
||||||
if (GfuiScreen == screen) {
|
if (GfuiScreen == screen) {
|
||||||
GfuiScreenDeactivate();
|
GfuiScreenDeactivate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,15 +25,42 @@
|
||||||
int NumberOfScreens = 0;
|
int NumberOfScreens = 0;
|
||||||
tGfuiScreen* OwnerOfScreens[MAXSCREENS];
|
tGfuiScreen* OwnerOfScreens[MAXSCREENS];
|
||||||
|
|
||||||
|
// Register all screens that are allocated
|
||||||
void RegisterScreens(void* screen)
|
void RegisterScreens(void* screen)
|
||||||
{
|
{
|
||||||
tGfuiScreen* _screen = (tGfuiScreen*) screen;
|
tGfuiScreen* _screen = (tGfuiScreen*) screen;
|
||||||
|
|
||||||
|
// Find a deleted entry
|
||||||
|
for (int I = 0; I < NumberOfScreens; I++)
|
||||||
|
{
|
||||||
|
if (OwnerOfScreens[I] == NULL)
|
||||||
|
{
|
||||||
|
OwnerOfScreens[I] = _screen;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (NumberOfScreens < MAXSCREENS)
|
if (NumberOfScreens < MAXSCREENS)
|
||||||
OwnerOfScreens[NumberOfScreens++] = _screen;
|
OwnerOfScreens[NumberOfScreens++] = _screen;
|
||||||
else
|
else
|
||||||
GfLogInfo("NumberOfScreens: %d > MAXSCREENS\n", NumberOfScreens);
|
GfLogInfo("NumberOfScreens: %d > MAXSCREENS\n", NumberOfScreens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unregister all screens that are released
|
||||||
|
void UnregisterScreens(void* screen)
|
||||||
|
{
|
||||||
|
// Find the entry
|
||||||
|
for (int I = 0; I <= NumberOfScreens; I++)
|
||||||
|
{
|
||||||
|
if (OwnerOfScreens[I] == screen)
|
||||||
|
{
|
||||||
|
OwnerOfScreens[I] = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free screens that are stil allocated
|
||||||
void FreeScreens()
|
void FreeScreens()
|
||||||
{
|
{
|
||||||
// For debugging purposes:
|
// For debugging purposes:
|
||||||
|
@ -41,17 +68,10 @@ void FreeScreens()
|
||||||
|
|
||||||
for (int I = 0; I <= NumberOfScreens; I++)
|
for (int I = 0; I <= NumberOfScreens; I++)
|
||||||
{
|
{
|
||||||
// This screen is corrupted!
|
|
||||||
// TODO: Find out why
|
|
||||||
if (I == 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Get the screen from the owner
|
// Get the screen from the owner
|
||||||
tGfuiScreen* screen = OwnerOfScreens[I];
|
tGfuiScreen* screen = OwnerOfScreens[I];
|
||||||
if (screen)
|
if (screen)
|
||||||
{
|
|
||||||
GfuiScreenRelease(screen); // Free all resources
|
GfuiScreenRelease(screen); // Free all resources
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Back to normal mode
|
// Back to normal mode
|
||||||
|
@ -62,6 +82,7 @@ void FreeScreens()
|
||||||
#else
|
#else
|
||||||
void RegisterScreens(void* screen){};
|
void RegisterScreens(void* screen){};
|
||||||
void FreeScreens(){};
|
void FreeScreens(){};
|
||||||
|
void UnregisterScreens(void* screen){};
|
||||||
#endif
|
#endif
|
||||||
// ... WDB test
|
// ... WDB test
|
||||||
|
|
||||||
|
@ -75,6 +96,7 @@ void GfuiShutdown(void)
|
||||||
{
|
{
|
||||||
gfuiShutdown();
|
gfuiShutdown();
|
||||||
|
|
||||||
|
// Free screens that are stil allocated
|
||||||
FreeScreens();
|
FreeScreens();
|
||||||
|
|
||||||
GfScrShutdown();
|
GfScrShutdown();
|
||||||
|
|
|
@ -799,6 +799,7 @@ inline GfuiApplication& GfuiApp()
|
||||||
#define MAXSCREENS 100
|
#define MAXSCREENS 100
|
||||||
void RegisterScreens(void* screen);
|
void RegisterScreens(void* screen);
|
||||||
void FreeScreens();
|
void FreeScreens();
|
||||||
|
void UnregisterScreens(void* screen);
|
||||||
|
|
||||||
#endif /* __TGFCLIENT__H__ */
|
#endif /* __TGFCLIENT__H__ */
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ main(int argc, char *argv[])
|
||||||
// while allocation!
|
// while allocation!
|
||||||
|
|
||||||
// For hunting of corrupted memory blocks comment the following line
|
// For hunting of corrupted memory blocks comment the following line
|
||||||
GfMemoryManagerSetup(4); // Add 4 bytes per block
|
//GfMemoryManagerSetup(4); // Add 4 bytes per block
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// ... WDB test
|
// ... WDB test
|
||||||
|
|
Loading…
Reference in a new issue