Game Development Community

Memory Leak in WinFont.cc, TGE 1.4

by Duncan Gray · in Torque Game Engine · 01/25/2006 (8:58 pm) · 4 replies

I've added a function to memory manager to produce a list of places where memory has been created but not destroyed.

I then started a mission, exited the mission, ran the function to get a list of things not destroyed after the mission. I got a l- o- n- g list...

I'm still checking all of them but number one so far is in
PlatformFont::CharInfo &WinFont::getCharInfo(const UTF16 ch) const
at line 310 in WinFont.cc

c.bitmapData = new U8[c.width * c.height];

Everytime getCharInfo gets called, that bitmapData gets created.
c then gets returned as the return parameter but the calling functions don't delete the bitmapData.

A quick search shows that getCharInfo gets called from 46 different locations in TGE.

Example in dlg/gfont.cc
U32 GOldFont::getStrNWidth(const char *str, U32 n) const
{
   AssertFatal(str != NULL, "GOldFont::getStrNWidth: String is NULL");

   if (str == NULL)   
      return(0);
      
   U32 totWidth = 0;
   const char *curChar;
   const char *endStr;
   for (curChar = str, endStr = str + n; curChar < endStr; curChar++)
   {
      if(isValidChar(*curChar))
      {
         [b]const CharInfo& rChar = getCharInfo(*curChar);[/b]
         totWidth += rChar.xIncrement;
      }
      else if (*curChar == '\t')
      {
         [b]const CharInfo& rChar = getCharInfo(' ');[/b]
         totWidth += rChar.xIncrement * TabWidthInSpaces;
      }
   }

   return(totWidth);
}

The fix, I assume, would be to delete it in all places where its called, or pass a bool to getCharInfo to only create the bitmapdata for those calling classes which need it etc.

#1
01/25/2006 (11:14 pm)
Your leak detector would make a great resource. You should post it.

I'm sure there are plenty of areas in the memory dept that could use some TLC. Good job tracking some of them down.

B--
#2
01/26/2006 (12:06 am)
I can't confirm 100% that this a leak, but these are areas of memory which were allocated and not de-allocated/deleted when the mission ended. It sure looks like a leak but the engine experts should investigate and confirm it.
#3
01/26/2006 (12:53 pm)
I posted the experimental leak detector as a resource Happy hunting.
#4
01/26/2006 (3:15 pm)
Hmm. I think you have gotten some code confused ...

There are two versions of the font rendering code. GOldFont and GFont (in GNewFont.cc, I'll call it GNewFont in this post for clarity). GOldFont is the original, non-unicode version of the font renderer. GNewFont is the new font renderer that supports Unicode.

GOldFont uses its own getCharInfo(), which is a member of the GOldFont class. This is where you are assuming the return is used, but that code is only used in non-Unicode builds. GOldFont caches all the glyphs when the font is created. GOldFont::getCharInfo() does not allocate the bitmap data, and thus it does not need to be freed.

GNewFont does not cache the glyphs when the font is created, rather it caches them on the fly when a character is needed. This was done because of the sheer number of characters in Unicode. PlatformFont provides the API to obtain the glyphs. winFont.cc implements WinFont, which is the PlatformFont implementation for Windows. This is where you are seeing the alloc.

GNewFont manages the information returned by PlatformFont::getCharInfo() and *does* free it correctly when the font is freed. However, GNewFont had to be a drop in replacement for GOldFont, so it also implements a getCharInfo() method of it's own. This one will use its cached data if it exists, or create the cached data if it doesnt.

Hopefully that clears it up :)

T.