forked from speed-dreams/speed-dreams-code
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:
parent
f8f4ea55a3
commit
27a2db6688
12 changed files with 146 additions and 45 deletions
|
@ -38,6 +38,7 @@
|
|||
#endif
|
||||
|
||||
#include <portability.h>
|
||||
#include "..\tgfdata\tgfdata.h"
|
||||
|
||||
#include "tgf.hpp"
|
||||
|
||||
|
@ -213,6 +214,12 @@ void GfApplication::restart()
|
|||
|
||||
// Delete the event loop if any.
|
||||
delete _pEventLoop;
|
||||
_pEventLoop = 0;
|
||||
|
||||
// Reset the Memory Manager
|
||||
#ifdef __DEBUG_MEMORYMANAGER__
|
||||
(*ReleaseData)();
|
||||
#endif
|
||||
|
||||
// Restart the process, using same command line args.
|
||||
// 1) The process executable path-name is the 1st arg left untouched.
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <windows.h>
|
||||
#include <crtdbg.h>
|
||||
#include <assert.h>
|
||||
#define GetRetAddrs __builtin_return_address(0)
|
||||
#define GetRetAddrs GCCRetAddrs
|
||||
// ... 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 _ReturnAddress()
|
||||
#define GetRetAddrs _ReturnAddress
|
||||
// ... VC++
|
||||
#endif
|
||||
// ... Windows
|
||||
|
@ -62,6 +62,18 @@
|
|||
//----------------------------------------------------------------------------*
|
||||
static tMemoryManager* GfMM = NULL; // The one and only memory manager!
|
||||
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
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||
|
@ -76,7 +88,7 @@ static unsigned int GfMM_Counter = 0; // Counter of memory blocks
|
|||
//ExternC 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);
|
||||
}
|
||||
//============================================================================*
|
||||
|
@ -96,7 +108,7 @@ void operator delete (void* b)
|
|||
//----------------------------------------------------------------------------*
|
||||
ExternC void* _tgf_win_malloc(size_t size)
|
||||
{
|
||||
void* retAddr = GetRetAddrs;
|
||||
void* retAddr = GetRetAddrs();
|
||||
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)
|
||||
{
|
||||
void* retAddr = GetRetAddrs;
|
||||
void* retAddr = GetRetAddrs();
|
||||
void* p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||
memset(p, 0, num * size);
|
||||
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)
|
||||
{
|
||||
void* retAddr = GetRetAddrs;
|
||||
void* retAddr = GetRetAddrs();
|
||||
|
||||
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)
|
||||
{
|
||||
void* retAddr = GetRetAddrs;
|
||||
void* retAddr = GetRetAddrs();
|
||||
|
||||
char * s = (char*) GfMemoryManagerAlloc(
|
||||
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
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
@ -453,7 +465,7 @@ bool GfMemoryManagerAllocate(void)
|
|||
//============================================================================*
|
||||
// Destroy the one and only global memory manager and it's allocated data
|
||||
//----------------------------------------------------------------------------*
|
||||
void GfMemoryManagerRelease(void)
|
||||
void GfMemoryManagerRelease(bool Dump)
|
||||
{
|
||||
int LeakSizeTotal = 0;
|
||||
int LeakSizeNewTotal = 0;
|
||||
|
@ -510,45 +522,56 @@ void GfMemoryManagerRelease(void)
|
|||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,"\nMemory manager leak statistics:\n\n");
|
||||
|
||||
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 (Dump)
|
||||
|
||||
{
|
||||
if (MM->Hist[I] > 0)
|
||||
fprintf(stderr,"%04.4d : %d\n",I,MM->Hist[I]);
|
||||
fprintf(stderr,"\nMemory manager leak statistics:\n\n");
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
fprintf(stderr,"\nPress [Enter] to close the program\n");
|
||||
getchar();
|
||||
if (Dump)
|
||||
{
|
||||
fprintf(stderr,"\nPress [Enter] to close the program\n");
|
||||
getchar();
|
||||
}
|
||||
}
|
||||
//============================================================================*
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
// Interface
|
||||
//
|
||||
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 void GfMemoryManagerSetup(int AddedSpace);
|
||||
TGF_API void GfMemoryManagerDoAccept(void);
|
||||
|
|
|
@ -238,6 +238,9 @@ class TGF_API GfApplication
|
|||
//! Restart the app.
|
||||
virtual void restart();
|
||||
|
||||
// Allow clean restart
|
||||
void (*ReleaseData)();
|
||||
|
||||
protected:
|
||||
|
||||
//! Print a short help about using the command line.
|
||||
|
|
|
@ -775,6 +775,8 @@ GfuiHookCreate(void *userDataOnActivate, tfuiCallback onActivate)
|
|||
screen->onActivate = onActivate;
|
||||
screen->userActData = userDataOnActivate;
|
||||
screen->onlyCallback = 1;
|
||||
|
||||
RegisterScreens(screen);
|
||||
|
||||
return (void*)screen;
|
||||
}
|
||||
|
|
|
@ -298,6 +298,7 @@ typedef struct GfuiKey
|
|||
/* screen definition */
|
||||
typedef struct
|
||||
{
|
||||
int ScreenID; /* Identify screen in registration */
|
||||
float width, height; /* in menu/screen objects coordinate system */
|
||||
GfuiColor bgColor; /* RGBA */
|
||||
GLuint bgImage; /* Should always be 2^N x 2^P (for low-end graphic hardwares) */
|
||||
|
|
|
@ -775,5 +775,6 @@ gfuiReleaseGrButton(tGfuiObject *obj)
|
|||
GfTexFreeTexture(button->focused);
|
||||
GfTexFreeTexture(button->pushed);
|
||||
|
||||
freez(button->userDataOnFocus);
|
||||
free(obj);
|
||||
}//gfuiReleaseGrButton
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#ifdef __DEBUG_MEMORYMANAGER__
|
||||
|
||||
// Avoid memory leaks ...
|
||||
int NextScreenID = 0;
|
||||
int NumberOfScreens = 0;
|
||||
tGfuiScreen* OwnerOfScreens[MAXSCREENS];
|
||||
|
||||
|
@ -29,6 +30,7 @@ tGfuiScreen* OwnerOfScreens[MAXSCREENS];
|
|||
void RegisterScreens(void* screen)
|
||||
{
|
||||
tGfuiScreen* _screen = (tGfuiScreen*) screen;
|
||||
_screen->ScreenID = ++NextScreenID;
|
||||
|
||||
// Find a deleted entry
|
||||
for (int I = 0; I < NumberOfScreens; I++)
|
||||
|
@ -66,7 +68,7 @@ void FreeScreens()
|
|||
// For debugging purposes:
|
||||
//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
|
||||
tGfuiScreen* screen = OwnerOfScreens[I];
|
||||
|
|
|
@ -41,9 +41,31 @@
|
|||
#include <iuserinterface.h>
|
||||
|
||||
// WDB test ...
|
||||
// Use the define to enable the memorymanager for hunting memory leaks
|
||||
#ifdef __DEBUG_MEMORYMANAGER__
|
||||
#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
|
||||
// ... WDB test
|
||||
|
||||
|
@ -156,11 +178,19 @@ main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
// Load the user interface module (graphical or text-only UI).
|
||||
// WDB test ...
|
||||
#ifdef __DEBUG_MEMORYMANAGER__
|
||||
pmodUserItf =
|
||||
#else
|
||||
GfModule* pmodUserItf =
|
||||
#endif
|
||||
GfModule::load("modules/userinterface", (bTextOnly ? "textonly" : "legacymenu"));
|
||||
|
||||
// Check that it implements IUserInterface.
|
||||
#ifdef __DEBUG_MEMORYMANAGER__
|
||||
#else
|
||||
IUserInterface* piUserItf = 0;
|
||||
#endif
|
||||
if (pmodUserItf)
|
||||
{
|
||||
piUserItf = pmodUserItf->getInterface<IUserInterface>();
|
||||
|
@ -175,10 +205,18 @@ main(int argc, char *argv[])
|
|||
void* hREParams =
|
||||
GfParmReadFile(ossParm.str().c_str(), GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
||||
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);
|
||||
#endif
|
||||
|
||||
// Check that it implements IRaceEngine.
|
||||
#ifdef __DEBUG_MEMORYMANAGER__
|
||||
#else
|
||||
IRaceEngine* piRaceEngine = 0;
|
||||
#endif
|
||||
if (pmodRaceEngine)
|
||||
{
|
||||
piRaceEngine = pmodRaceEngine->getInterface<IRaceEngine>();
|
||||
|
@ -193,6 +231,11 @@ main(int argc, char *argv[])
|
|||
|
||||
if (piUserItf && piRaceEngine)
|
||||
{
|
||||
#ifdef __DEBUG_MEMORYMANAGER__
|
||||
// Allow to avoid memory leaks at restart
|
||||
pApp->ReleaseData = &ReleaseData;
|
||||
#endif
|
||||
|
||||
// Enter the user interface.
|
||||
if (piUserItf->activate())
|
||||
{
|
||||
|
|
|
@ -424,6 +424,11 @@ DisplayMenu::DisplayMenu()
|
|||
#endif
|
||||
}
|
||||
|
||||
DisplayMenu::~DisplayMenu()
|
||||
{
|
||||
free(_aColorDepths);
|
||||
}
|
||||
|
||||
bool DisplayMenu::initialize(void *pPreviousMenu)
|
||||
{
|
||||
// Save the menu to return to.
|
||||
|
@ -517,5 +522,13 @@ void* DisplayMenuInit(void *pPreviousMenu)
|
|||
return PDisplayMenu->getMenuHandle();
|
||||
}
|
||||
|
||||
/** Relase the display options menu screen.
|
||||
@ingroup screen
|
||||
*/
|
||||
void DisplayMenuRelease(void)
|
||||
{
|
||||
delete PDisplayMenu;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ class DisplayMenu : public GfuiMenuScreen
|
|||
public:
|
||||
|
||||
DisplayMenu();
|
||||
~DisplayMenu();
|
||||
|
||||
bool initialize(void* pPreviousMenu);
|
||||
|
||||
enum EDisplayMode { eFullScreen = 0, eWindowed = 1, nDisplayModes };
|
||||
|
@ -105,5 +107,6 @@ private:
|
|||
};
|
||||
|
||||
extern void* DisplayMenuInit(void* pPreviousMenu);
|
||||
extern void DisplayMenuRelease(void);
|
||||
|
||||
#endif //_DISPLAYCONFIG_H_
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "racescreens.h"
|
||||
|
||||
#include "legacymenu.h"
|
||||
#include "displayconfig.h"
|
||||
|
||||
|
||||
// The LegacyMenu singleton.
|
||||
|
@ -62,6 +63,8 @@ int closeGfModule()
|
|||
if (LegacyMenu::_pSelf)
|
||||
GfModule::unregister(LegacyMenu::_pSelf);
|
||||
|
||||
DisplayMenuRelease();
|
||||
|
||||
// Delete the (only) module instance.
|
||||
delete LegacyMenu::_pSelf;
|
||||
LegacyMenu::_pSelf = 0;
|
||||
|
|
Loading…
Reference in a new issue