Implemented restart of Memory Manager while restart()

DisplayMenu allocates data but had no destructor to free it
GButtons did not free userDataOnFocus

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@5839 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: ca943f98b94e089d277b533d709d601fb0ff39fd
Former-commit-id: 50b1f006e658b859c9f30d1200fd4610612bf330
This commit is contained in:
wdbee 2014-11-15 15:05:25 +00:00
parent f8f4ea55a3
commit 27a2db6688
12 changed files with 146 additions and 45 deletions

View file

@ -38,6 +38,7 @@
#endif #endif
#include <portability.h> #include <portability.h>
#include "..\tgfdata\tgfdata.h"
#include "tgf.hpp" #include "tgf.hpp"
@ -213,6 +214,12 @@ void GfApplication::restart()
// Delete the event loop if any. // Delete the event loop if any.
delete _pEventLoop; delete _pEventLoop;
_pEventLoop = 0;
// Reset the Memory Manager
#ifdef __DEBUG_MEMORYMANAGER__
(*ReleaseData)();
#endif
// Restart the process, using same command line args. // Restart the process, using same command line args.
// 1) The process executable path-name is the 1st arg left untouched. // 1) The process executable path-name is the 1st arg left untouched.

View file

@ -29,7 +29,7 @@
#include <windows.h> #include <windows.h>
#include <crtdbg.h> #include <crtdbg.h>
#include <assert.h> #include <assert.h>
#define GetRetAddrs __builtin_return_address(0) #define GetRetAddrs GCCRetAddrs
// ... MinGW // ... MinGW
#else #else
// VC++ ... // VC++ ...
@ -40,7 +40,7 @@
#include <intrin.h> #include <intrin.h>
#pragma intrinsic(_ReturnAddress) #pragma intrinsic(_ReturnAddress)
#undef ANSI_ISO // Old VC++ versions returning NULL instead of exception #undef ANSI_ISO // Old VC++ versions returning NULL instead of exception
#define GetRetAddrs _ReturnAddress() #define GetRetAddrs _ReturnAddress
// ... VC++ // ... VC++
#endif #endif
// ... Windows // ... Windows
@ -62,6 +62,18 @@
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
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
//============================================================================*
#if defined(__MINGW32__)
//============================================================================*
// GCC allows to set the level parameter, we use 0 to get the same as for VC++
//----------------------------------------------------------------------------*
void* GCCRetAddrs(void)
{
return __builtin_return_address(0);
}
//============================================================================*
#endif
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
// ... Implementation // ... Implementation
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++* //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
@ -76,7 +88,7 @@ static unsigned int GfMM_Counter = 0; // Counter of memory blocks
//ExternC void* operator new (size_t size) //ExternC void* operator new (size_t size)
void* operator new (size_t size) void* operator new (size_t size)
{ {
void* retAddr = GetRetAddrs; void* retAddr = GetRetAddrs();
return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_NEW,retAddr); return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_NEW,retAddr);
} }
//============================================================================* //============================================================================*
@ -96,7 +108,7 @@ void operator delete (void* b)
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
ExternC void* _tgf_win_malloc(size_t size) ExternC void* _tgf_win_malloc(size_t size)
{ {
void* retAddr = GetRetAddrs; void* retAddr = GetRetAddrs();
return GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr); return GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
} }
//============================================================================* //============================================================================*
@ -115,7 +127,7 @@ ExternC void _tgf_win_free(void* b)
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
ExternC void* _tgf_win_calloc(size_t num, size_t size) ExternC void* _tgf_win_calloc(size_t num, size_t size)
{ {
void* retAddr = GetRetAddrs; void* retAddr = GetRetAddrs();
void* p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr); void* p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
memset(p, 0, num * size); memset(p, 0, num * size);
return p; return p;
@ -127,7 +139,7 @@ ExternC void* _tgf_win_calloc(size_t num, size_t size)
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
ExternC void* _tgf_win_realloc(void* memblock, size_t size) ExternC void* _tgf_win_realloc(void* memblock, size_t size)
{ {
void* retAddr = GetRetAddrs; void* retAddr = GetRetAddrs();
if (size == 0) if (size == 0)
{ {
@ -175,7 +187,7 @@ ExternC void* _tgf_win_realloc(void* memblock, size_t size)
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
ExternC char * _tgf_win_strdup(const char * str) ExternC char * _tgf_win_strdup(const char * str)
{ {
void* retAddr = GetRetAddrs; void* retAddr = GetRetAddrs();
char * s = (char*) GfMemoryManagerAlloc( char * s = (char*) GfMemoryManagerAlloc(
strlen(str)+1,GF_MM_ALLOCTYPE_MALLOC,retAddr); strlen(str)+1,GF_MM_ALLOCTYPE_MALLOC,retAddr);
@ -295,7 +307,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 371835 // ID of block you are looking for #define IDTOSTOP 280452 // ID of block you are looking for
if (ID == IDTOSTOP) if (ID == IDTOSTOP)
{ {
@ -453,7 +465,7 @@ bool GfMemoryManagerAllocate(void)
//============================================================================* //============================================================================*
// 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) void GfMemoryManagerRelease(bool Dump)
{ {
int LeakSizeTotal = 0; int LeakSizeTotal = 0;
int LeakSizeNewTotal = 0; int LeakSizeNewTotal = 0;
@ -510,45 +522,56 @@ void GfMemoryManagerRelease(void)
} }
} }
fprintf(stderr,"\nMemory manager leak statistics:\n\n"); if (Dump)
fprintf(stderr,"Number of allocated blocks : %d\n",GfMM_Counter);
fprintf(stderr,"Number of memory leaks : %d\n\n",n);
fprintf(stderr,"Total leak size new/delete : %d [Byte]\n",LeakSizeNewTotal);
fprintf(stderr,"Total leak size malloc/free : %d [Byte]\n",LeakSizeMallocTotal);
fprintf(stderr,"Total leak size total : %d [Byte]\n\n",LeakSizeTotal);
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",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,"\nMemory manager leak statistics:\n\n");
fprintf(stderr,"%04.4d : %d\n",I,MM->Hist[I]);
fprintf(stderr,"Number of allocated blocks : %d\n",GfMM_Counter);
fprintf(stderr,"Number of memory leaks : %d\n\n",n);
fprintf(stderr,"Total leak size new/delete : %d [Byte]\n",LeakSizeNewTotal);
fprintf(stderr,"Total leak size malloc/free : %d [Byte]\n",LeakSizeMallocTotal);
fprintf(stderr,"Total leak size total : %d [Byte]\n\n",LeakSizeTotal);
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",MaxLeakSizeTotal);
fprintf(stderr,"\nPress [Enter] to show next part of info\n");
getchar(); // Stop to show leaks first
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 delete(Block); // Delete the memory manager itself
} }
fprintf(stderr,"\nPress [Enter] to close the program\n"); if (Dump)
getchar(); {
fprintf(stderr,"\nPress [Enter] to close the program\n");
getchar();
}
} }
//============================================================================* //============================================================================*

View file

@ -29,7 +29,7 @@
// Interface // Interface
// //
TGF_API bool GfMemoryManagerAllocate(void); // Initialize memory manager TGF_API bool GfMemoryManagerAllocate(void); // Initialize memory manager
TGF_API void GfMemoryManagerRelease(void); // Release memory manager at Shutdown TGF_API void GfMemoryManagerRelease(bool Dump = true); // Release memory manager at Shutdown
TGF_API bool GfMemoryManagerRunning(void); // Is the memory manager running? TGF_API bool GfMemoryManagerRunning(void); // Is the memory manager running?
TGF_API void GfMemoryManagerSetup(int AddedSpace); TGF_API void GfMemoryManagerSetup(int AddedSpace);
TGF_API void GfMemoryManagerDoAccept(void); TGF_API void GfMemoryManagerDoAccept(void);

View file

@ -238,6 +238,9 @@ class TGF_API GfApplication
//! Restart the app. //! Restart the app.
virtual void restart(); virtual void restart();
// Allow clean restart
void (*ReleaseData)();
protected: protected:
//! Print a short help about using the command line. //! Print a short help about using the command line.

View file

@ -776,6 +776,8 @@ GfuiHookCreate(void *userDataOnActivate, tfuiCallback onActivate)
screen->userActData = userDataOnActivate; screen->userActData = userDataOnActivate;
screen->onlyCallback = 1; screen->onlyCallback = 1;
RegisterScreens(screen);
return (void*)screen; return (void*)screen;
} }

View file

@ -298,6 +298,7 @@ typedef struct GfuiKey
/* screen definition */ /* screen definition */
typedef struct typedef struct
{ {
int ScreenID; /* Identify screen in registration */
float width, height; /* in menu/screen objects coordinate system */ float width, height; /* in menu/screen objects coordinate system */
GfuiColor bgColor; /* RGBA */ GfuiColor bgColor; /* RGBA */
GLuint bgImage; /* Should always be 2^N x 2^P (for low-end graphic hardwares) */ GLuint bgImage; /* Should always be 2^N x 2^P (for low-end graphic hardwares) */

View file

@ -775,5 +775,6 @@ gfuiReleaseGrButton(tGfuiObject *obj)
GfTexFreeTexture(button->focused); GfTexFreeTexture(button->focused);
GfTexFreeTexture(button->pushed); GfTexFreeTexture(button->pushed);
freez(button->userDataOnFocus);
free(obj); free(obj);
}//gfuiReleaseGrButton }//gfuiReleaseGrButton

View file

@ -22,6 +22,7 @@
#ifdef __DEBUG_MEMORYMANAGER__ #ifdef __DEBUG_MEMORYMANAGER__
// Avoid memory leaks ... // Avoid memory leaks ...
int NextScreenID = 0;
int NumberOfScreens = 0; int NumberOfScreens = 0;
tGfuiScreen* OwnerOfScreens[MAXSCREENS]; tGfuiScreen* OwnerOfScreens[MAXSCREENS];
@ -29,6 +30,7 @@ tGfuiScreen* OwnerOfScreens[MAXSCREENS];
void RegisterScreens(void* screen) void RegisterScreens(void* screen)
{ {
tGfuiScreen* _screen = (tGfuiScreen*) screen; tGfuiScreen* _screen = (tGfuiScreen*) screen;
_screen->ScreenID = ++NextScreenID;
// Find a deleted entry // Find a deleted entry
for (int I = 0; I < NumberOfScreens; I++) for (int I = 0; I < NumberOfScreens; I++)
@ -66,7 +68,7 @@ void FreeScreens()
// For debugging purposes: // For debugging purposes:
//doaccept(); // Do not free the blocks, just take it out of the list //doaccept(); // Do not free the blocks, just take it out of the list
for (int I = 0; I <= NumberOfScreens; I++) for (int I = 0; I < NumberOfScreens; I++)
{ {
// Get the screen from the owner // Get the screen from the owner
tGfuiScreen* screen = OwnerOfScreens[I]; tGfuiScreen* screen = OwnerOfScreens[I];

View file

@ -41,9 +41,31 @@
#include <iuserinterface.h> #include <iuserinterface.h>
// WDB test ... // WDB test ...
// Use the define to enable the memorymanager for hunting memory leaks
#ifdef __DEBUG_MEMORYMANAGER__ #ifdef __DEBUG_MEMORYMANAGER__
#include "memmanager.h" #include "memmanager.h"
IUserInterface* piUserItf = 0;
GfModule* pmodUserItf = NULL;
IRaceEngine* piRaceEngine = 0;
GfModule* pmodRaceEngine = NULL;
void ReleaseData(void)
{
if (piUserItf && piRaceEngine)
{
// Shutdown and unload the user interface and race engine modules.
piUserItf->shutdown();
piRaceEngine->shutdown();
GfModule::unload(pmodUserItf);
GfModule::unload(pmodRaceEngine);
// Shutdown the data layer.
//GfData::shutdown(); << causes crashes if called from here
GfMemoryManagerRelease(false); // Release the memeory manager without dump
}
}
#endif #endif
// ... WDB test // ... WDB test
@ -156,11 +178,19 @@ main(int argc, char *argv[])
} }
// Load the user interface module (graphical or text-only UI). // Load the user interface module (graphical or text-only UI).
// WDB test ...
#ifdef __DEBUG_MEMORYMANAGER__
pmodUserItf =
#else
GfModule* pmodUserItf = GfModule* pmodUserItf =
#endif
GfModule::load("modules/userinterface", (bTextOnly ? "textonly" : "legacymenu")); GfModule::load("modules/userinterface", (bTextOnly ? "textonly" : "legacymenu"));
// Check that it implements IUserInterface. // Check that it implements IUserInterface.
#ifdef __DEBUG_MEMORYMANAGER__
#else
IUserInterface* piUserItf = 0; IUserInterface* piUserItf = 0;
#endif
if (pmodUserItf) if (pmodUserItf)
{ {
piUserItf = pmodUserItf->getInterface<IUserInterface>(); piUserItf = pmodUserItf->getInterface<IUserInterface>();
@ -175,10 +205,18 @@ main(int argc, char *argv[])
void* hREParams = void* hREParams =
GfParmReadFile(ossParm.str().c_str(), GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); GfParmReadFile(ossParm.str().c_str(), GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
const char* pszModName = GfParmGetStr(hREParams, "Modules", "racing", "standardgame"); const char* pszModName = GfParmGetStr(hREParams, "Modules", "racing", "standardgame");
#ifdef __DEBUG_MEMORYMANAGER__
pmodRaceEngine = GfModule::load("modules/racing", pszModName);
#else
GfModule* pmodRaceEngine = GfModule::load("modules/racing", pszModName); GfModule* pmodRaceEngine = GfModule::load("modules/racing", pszModName);
#endif
// Check that it implements IRaceEngine. // Check that it implements IRaceEngine.
#ifdef __DEBUG_MEMORYMANAGER__
#else
IRaceEngine* piRaceEngine = 0; IRaceEngine* piRaceEngine = 0;
#endif
if (pmodRaceEngine) if (pmodRaceEngine)
{ {
piRaceEngine = pmodRaceEngine->getInterface<IRaceEngine>(); piRaceEngine = pmodRaceEngine->getInterface<IRaceEngine>();
@ -193,6 +231,11 @@ main(int argc, char *argv[])
if (piUserItf && piRaceEngine) if (piUserItf && piRaceEngine)
{ {
#ifdef __DEBUG_MEMORYMANAGER__
// Allow to avoid memory leaks at restart
pApp->ReleaseData = &ReleaseData;
#endif
// Enter the user interface. // Enter the user interface.
if (piUserItf->activate()) if (piUserItf->activate())
{ {

View file

@ -424,6 +424,11 @@ DisplayMenu::DisplayMenu()
#endif #endif
} }
DisplayMenu::~DisplayMenu()
{
free(_aColorDepths);
}
bool DisplayMenu::initialize(void *pPreviousMenu) bool DisplayMenu::initialize(void *pPreviousMenu)
{ {
// Save the menu to return to. // Save the menu to return to.
@ -517,5 +522,13 @@ void* DisplayMenuInit(void *pPreviousMenu)
return PDisplayMenu->getMenuHandle(); return PDisplayMenu->getMenuHandle();
} }
/** Relase the display options menu screen.
@ingroup screen
*/
void DisplayMenuRelease(void)
{
delete PDisplayMenu;
}

View file

@ -33,6 +33,8 @@ class DisplayMenu : public GfuiMenuScreen
public: public:
DisplayMenu(); DisplayMenu();
~DisplayMenu();
bool initialize(void* pPreviousMenu); bool initialize(void* pPreviousMenu);
enum EDisplayMode { eFullScreen = 0, eWindowed = 1, nDisplayModes }; enum EDisplayMode { eFullScreen = 0, eWindowed = 1, nDisplayModes };
@ -105,5 +107,6 @@ private:
}; };
extern void* DisplayMenuInit(void* pPreviousMenu); extern void* DisplayMenuInit(void* pPreviousMenu);
extern void DisplayMenuRelease(void);
#endif //_DISPLAYCONFIG_H_ #endif //_DISPLAYCONFIG_H_

View file

@ -38,6 +38,7 @@
#include "racescreens.h" #include "racescreens.h"
#include "legacymenu.h" #include "legacymenu.h"
#include "displayconfig.h"
// The LegacyMenu singleton. // The LegacyMenu singleton.
@ -62,6 +63,8 @@ int closeGfModule()
if (LegacyMenu::_pSelf) if (LegacyMenu::_pSelf)
GfModule::unregister(LegacyMenu::_pSelf); GfModule::unregister(LegacyMenu::_pSelf);
DisplayMenuRelease();
// Delete the (only) module instance. // Delete the (only) module instance.
delete LegacyMenu::_pSelf; delete LegacyMenu::_pSelf;
LegacyMenu::_pSelf = 0; LegacyMenu::_pSelf = 0;