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:
wdbee 2014-11-14 17:29:58 +00:00
parent 3d99d4edf3
commit 8a18586843
7 changed files with 269 additions and 202 deletions

View file

@ -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

View file

@ -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;

View file

@ -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)

View file

@ -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();
} }

View file

@ -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();

View file

@ -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__ */

View file

@ -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