Path: utzoo!attcan!uunet!husc6!bloom-beacon!gatech!rutgers!ucsd!ucbvax!hplabs!hp-pcd!hpcvlx!fred
From: fred@hpcvlx.HP.COM (Fred Taft)
Newsgroups: comp.windows.x
Subject: Re: HP's Xtk Bug Fixes
Message-ID: <1610035@hpcvlx.HP.COM>
Date: 15 Aug 88 18:11:48 GMT
References: <1610032@hpcvlx.HP.COM>
Organization: Hewlett-Packard Co., Corvallis, OR, USA
Lines: 176

VERSION:
	Xtk release 2

SYNOPSIS:
	Using XtParseTranslationTable() causes a program to grow without
        an upper bound.

DESCRIPTION:
        XtParseTranslationTable() returns a pointer to a translation
        state table, which in turn contains potentially many other
        pointers to blocks of memory (state records, action records, etc).
        Unfortunately, the toolkit does not provide a mechanism for 
        freeing up this memory once an application is done with it.

        It appears that the reason the memory is not freed up is because
        the toolkit caches these parsed translation table, thus
        potentially saving time (and space) if the same translation
        is ever parsed again.  However, our widget set parses many 
        (possibly 100 or more, depending upon what widgets you use),
        and each of the translation tables are unique.  
    
        If an application, such as a window manager, is creating and 
        destroying alot of widgets, it's size continues to grow because 
        all of these state tables are cached, but never used again after 
        the associated widget is destroyed.

        The patches which follow affect the following files:

           1) TMstate.c - Added XtDestroyStateTable(), which frees up
                       a translation state table and all underlying
                       malloc memory.

                       Modified MergeStates() to create new copies
                       of the parameter strings and array of string
                       pointers, rather than just copying the existing
                       pointers.

                       Removed the caching of the parsed event state
                       tables in XtOverrideTranslations and
                       XtAugmentTranslations.

                       Added a call to XtDestroyStateTable() in both
                       XtOverrideTranslations and XtAugmentTranslations,
                       to free up the widgets old translation state table.

           2) TMparse.c - Removed the caching of the parsed event state
                       table in XtParseTranslationTable().

           3) Core.c - Added a call to XtDestroyStateTable() in
                       CoreDestroy(), to free up the widgets state
                       table.

REPEAT-BY:
        Have a program which parses several unique translation tables,
        and watch the size of the program grow.

FIX:

/* This is a patch for Core.c */

279a280,287
> 
> 
>     /*  Destroy the translation state table  */
> 
>     XtDestroyStateTable (widget->core.widget_class, 
>                          widget->core.tm.translations);
> 
> 

/* This is a patch for TMparse.c */

1420a1421
>     int noArgs = 0;
1423a1425,1428
>     to.addr = NULL;
>     to.size = 0;
>     _CompileTranslations (NULL, &noArgs, &from, &to);
> /*
1425a1431
> */

/* This is a patch for TMparse.c */

865a866
>     register int i;
905c906,908
<            a->params = b->params;
---
> 
> 
> /*         a->params = b->params;   */
906a910,919
>            if (a->num_params > 0)
>               a->params = (char **) XtMalloc (sizeof (char *) * b->num_params);
>            else
>               a->params = NULL;
>            for (i = 0; i < b->num_params; i++)
>            {
>               a->params[i] = (char *) XtMalloc (strlen (b->params[i]) + 1);
>               strcpy (a->params[i], b->params[i]);
>            }
> 
1082a1096
>     int noArgs = 0;
1092a1107,1108
>     _MergeTranslations (NULL, &noArgs, &from, &to);
> /*
1094a1111
> */
1095a1113,1119
> 
>     /*  Destroy the translation state table  */
> 
>     XtDestroyStateTable (widget->core.widget_class, 
>                          widget->core.tm.translations);
> 
> 
1136a1161
>     int noArgs = 0;
1146a1172,1173
>     _MergeTranslations (NULL, &noArgs, &from, &to);
> /*
1148a1176
> */
1149a1178,1184
> 
>     /*  Destroy the translation state table  */
> 
>     XtDestroyStateTable (widget->core.widget_class, 
>                          widget->core.tm.translations);
> 
> 
1417a1453,1494
> 
> 
> /*  HP added translation state table deallocation procedure.  */
> /*  This is used by both toolkit functions and widgets to     */
> /*  eliminate a huge memory whole.                            */
> 
> XtDestroyStateTable (class, stateTable)
> 
>    WidgetClass    class;
>    XtTranslations stateTable;
> 
> {
>    register StatePtr  state, nextState;
>    register ActionPtr action, nextAction;
> 
>    /* Don't do anything if the state table is the widget class's state table */
>    if (stateTable && (stateTable != (XtTranslations)class->core_class.tm_table))
>    {
>       /* Free up each state record and all associated action records */
>       for (state = stateTable->head; state != NULL; )
>       {
>          for (action = state->actions; action != NULL; )
>          {
>             nextAction = action->next;
>             FreeActions(action);
>             action = nextAction;
>          }
> 
>          nextState = state->forw;
>          XtFree(state);
>          state = nextState;
>       }
> 
>       /* Free up quark Table, event object array and the state table */
>       XtFree(stateTable->quarkTable);
>       XtFree(stateTable->eventObjTbl);
>       XtFree(stateTable);
>    }
> }
> 
> 
>