diff --git a/src/libs/tgf/application.cpp b/src/libs/tgf/application.cpp index a33f54db7..bcf63a801 100644 --- a/src/libs/tgf/application.cpp +++ b/src/libs/tgf/application.cpp @@ -38,6 +38,7 @@ #endif #include +#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. diff --git a/src/libs/tgf/memmanager.cpp b/src/libs/tgf/memmanager.cpp index 5ca5db411..0bdc14023 100644 --- a/src/libs/tgf/memmanager.cpp +++ b/src/libs/tgf/memmanager.cpp @@ -29,7 +29,7 @@ #include #include #include - #define GetRetAddrs __builtin_return_address(0) + #define GetRetAddrs GCCRetAddrs // ... MinGW #else // VC++ ... @@ -40,7 +40,7 @@ #include #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(); + } } //============================================================================* diff --git a/src/libs/tgf/memmanager.h b/src/libs/tgf/memmanager.h index 7c44ff712..40532b399 100644 --- a/src/libs/tgf/memmanager.h +++ b/src/libs/tgf/memmanager.h @@ -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); diff --git a/src/libs/tgf/tgf.hpp b/src/libs/tgf/tgf.hpp index f5c4c313f..4e0c7768d 100644 --- a/src/libs/tgf/tgf.hpp +++ b/src/libs/tgf/tgf.hpp @@ -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. diff --git a/src/libs/tgfclient/gui.cpp b/src/libs/tgfclient/gui.cpp index 555b18f34..7c1df6840 100644 --- a/src/libs/tgfclient/gui.cpp +++ b/src/libs/tgfclient/gui.cpp @@ -775,6 +775,8 @@ GfuiHookCreate(void *userDataOnActivate, tfuiCallback onActivate) screen->onActivate = onActivate; screen->userActData = userDataOnActivate; screen->onlyCallback = 1; + + RegisterScreens(screen); return (void*)screen; } diff --git a/src/libs/tgfclient/gui.h b/src/libs/tgfclient/gui.h index 95a5a60f9..28b776ee1 100644 --- a/src/libs/tgfclient/gui.h +++ b/src/libs/tgfclient/gui.h @@ -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) */ diff --git a/src/libs/tgfclient/guibutton.cpp b/src/libs/tgfclient/guibutton.cpp index 7b20fdb5e..450a1f98f 100644 --- a/src/libs/tgfclient/guibutton.cpp +++ b/src/libs/tgfclient/guibutton.cpp @@ -775,5 +775,6 @@ gfuiReleaseGrButton(tGfuiObject *obj) GfTexFreeTexture(button->focused); GfTexFreeTexture(button->pushed); + freez(button->userDataOnFocus); free(obj); }//gfuiReleaseGrButton diff --git a/src/libs/tgfclient/tgfclient.cpp b/src/libs/tgfclient/tgfclient.cpp index 2f0ef8c3c..2d053927d 100644 --- a/src/libs/tgfclient/tgfclient.cpp +++ b/src/libs/tgfclient/tgfclient.cpp @@ -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]; diff --git a/src/main/main.cpp b/src/main/main.cpp index c7c9e50a1..054576de5 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -41,9 +41,31 @@ #include // 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(); @@ -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(); @@ -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()) { diff --git a/src/modules/userinterface/legacymenu/confscreens/displayconfig.cpp b/src/modules/userinterface/legacymenu/confscreens/displayconfig.cpp index 709dcfdc3..81bcaaaeb 100644 --- a/src/modules/userinterface/legacymenu/confscreens/displayconfig.cpp +++ b/src/modules/userinterface/legacymenu/confscreens/displayconfig.cpp @@ -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; +} + diff --git a/src/modules/userinterface/legacymenu/confscreens/displayconfig.h b/src/modules/userinterface/legacymenu/confscreens/displayconfig.h index b6d638580..866b0dec9 100644 --- a/src/modules/userinterface/legacymenu/confscreens/displayconfig.h +++ b/src/modules/userinterface/legacymenu/confscreens/displayconfig.h @@ -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_ diff --git a/src/modules/userinterface/legacymenu/legacymenu.cpp b/src/modules/userinterface/legacymenu/legacymenu.cpp index e7bc414ea..78b374313 100644 --- a/src/modules/userinterface/legacymenu/legacymenu.cpp +++ b/src/modules/userinterface/legacymenu/legacymenu.cpp @@ -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;