[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference bulova::decw_jan-89_to_nov-90

Title:DECWINDOWS 26-JAN-89 to 29-NOV-90
Notice:See 1639.0 for VMS V5.3 kit; 2043.0 for 5.4 IFT kit
Moderator:STAR::VATNE
Created:Mon Oct 30 1989
Last Modified:Mon Dec 31 1990
Last Successful Update:Fri Jun 06 1997
Number of topics:3726
Total number of notes:19516

2508.0. "XtDestroyWidget - Does it free up allocated memory" by SCOTMN::WOOD (Richard Wood - UK Workstation Support DTN 833 -3801) Fri Mar 23 1990 12:51

Hi,

  I have a customer who is running out of virtual memory, on the
face of it, simply because he is using XtDestroyWidget to free up
memory after he has finished using the widget. Is this right ?

  Having read the function description, it seems to be a bit vague
about when it does free the space. I have a piece of code below that just
creates, manages, unmanages and destroys a dialog box over and over again.
With a pgflquota of 10000 and wsquot of 2048, it crashes out with either
Insuffient Dynamic Memory or an ACCVIO ( taking about 4 - 5 minutes to fail ).

  Does anybody know what the limitations are( if any ) of using this routine.
Should the customer be reusing the same dialog box by simply doing a
set values ?

Here is the code :-

#include <stdio.h>
#include <decw$include/DwtAppl.h>       /* DECwindows Toolkit */

int main(argc, argv)
unsigned int argc;
char **argv;

{
Widget toplevel, bad_destroy,helloworldmain;
Arg arglist[2] ;
	
toplevel = XtInitialize(
		"Hi",	 			/* application name */
		"helloworldclass",              /* application class */
		NULL, 0,                        /* options */
		&argc, argv);                   /* command line parameters */

XtSetArg(arglist[0], XtNallowShellResize, TRUE );
XtSetValues(toplevel, arglist, 1);
	
XtSetArg(arglist[0], DwtNheight, 400 );
XtSetArg(arglist[1], DwtNwidth, 200 );
	
helloworldmain = DwtDialogBoxCreate (toplevel,
				"helloworld_main",
				arglist,
				2);
	
	
XtManageChild(helloworldmain);

XtRealizeWidget(toplevel);

XtSetArg(arglist[0], DwtNx, 100 );
XtSetArg(arglist[1], DwtNy, 100 );
XtSetArg(arglist[2], DwtNheight, 80 );
XtSetArg(arglist[3], DwtNwidth, 40 );

for (;;)
{
bad_destroy = DwtDialogBoxCreate (toplevel,
				"helloworld_main",
				arglist,
				4);

XtManageChild(bad_destroy);
XtUnmanageChild(bad_destroy);
XtDestroyWidget(bad_destroy);
}

XtMainLoop();
	
return (0);
}
T.RTitleUserPersonal
Name
DateLines
2508.1Is "dislike" too strong a word?DECWIN::KLEINFri Mar 23 1990 13:0520
>  Does anybody know what the limitations are( if any ) of using this routine.
>Should the customer be reusing the same dialog box by simply doing a
>set values ?

Absolutely.  I have heard numerous complaints about XtDestroyWidget, both
in its not really freeing resources and that it has (or at least had) bugs
that were causing applications to ACCVIO.

Even if destroyed widgets free their memory with XtFree, memory quickly becomes
fragmented and the VA space keeps growing.

My advice to anyone who asks is to NEVER use XtDestroyWidget.  The
freed resources are often not reusable and its is MUCH MUCH costlier
to destroy a widget and recreate it than to simply do some XtSetValues
to change what it looks like.

Put widgets on a free list rather than destroying them, and look there first
rather than always creating new ones.

-steve-
2508.2SCOTMN::WOODRichard Wood - UK Workstation Support DTN 833 -3801Mon Mar 26 1990 05:0215
  Thanks for the info, Steve, I must say, it does make pretty good sense,
I'll try and persuade the customer to change his approach !!!!

  Although I can't see how Virtual Memory can get fragmented with the
little test program in .0 ( creating and freeing the same dialog box ),
I can see how it may do with different widgets; on the whole I can't see
why you should need to destroy a widget if you need to recreate it at a 
later time.

  Does anybody else have any info on the use of XtDestroyWidget

Thanks

Richard
2508.3Will this problem be fixed?ZSAZSA::READINGSRichard ReadingsMon Mar 26 1990 11:095
Are there any plans to fix this problem in a future release of DECwindows, 
so that memory can be recovered?


Richard
2508.4Invalid test program...LEOVAX::TREGGIARIMon Apr 02 1990 17:4933
> XtRealizeWidget(toplevel);
>
> XtSetArg(arglist[0], DwtNx, 100 );
> XtSetArg(arglist[1], DwtNy, 100 );
> XtSetArg(arglist[2], DwtNheight, 80 );
> XtSetArg(arglist[3], DwtNwidth, 40 );
>
> for (;;)
> {
> bad_destroy = DwtDialogBoxCreate (toplevel,
>				"helloworld_main",
>				arglist,
>				4);
>
> XtManageChild(bad_destroy);
> XtUnmanageChild(bad_destroy);
> XtDestroyWidget(bad_destroy);
> }
> 
> XtMainLoop();

Your test program does not prove that creating and destroying dialog boxes
leaks memory.  Widgets attempt to give back all of their instance specific
memory when destroyed.  I don't know of any "leaks".  What your test program
is doing that will continually eat up memory, is ignoring the X event
queue.  Events keep getting queued, but nothing is ever read off...

Steve's suggestion of memory fragmentation is also possible, but I'd rewrite
you test program to keep the queue "clean" before I'd assume that that is
the problem.

Leo 
2508.5ThanksSCOTMN::WOODEl VaqueroThu Apr 05 1990 13:044
Thanks for the response, I'll give it a try.

Richard
2508.6Try using FAKE_VMREINIG::REINIGThis too shall changeFri Apr 06 1990 13:165
    If you are interested in tracking memory leaks and other memory
    problems, you may be interested in FAKE_VM.  See CLT::FAKE_VM for
    details.
    
                        August G. Reinig
2508.7XtDestroyWidget still a problemSCOTMN::WOODEl VaqueroThu May 17 1990 11:5939
Hi,

  I'm having to resurect this problem; the customer has now come back
with a more complex program to reproduce the problem. It takes into
account clearing out the event queue before destroying the widget. Also
instead of just creating and destroying one widget, it destroys the
whole hierarchy.

  Initially, I did suggest that using XtDestroyWidget was probably not
a good idea, but he was insistant that they needed to use it.

  I enclose the new program and also a cut down version of my own.
The customers version extends Virtual Address Space comparatively
quickly compared to my own, but seems to ACCVIO after a couple of minutes.

  My own version does basically the same as the customers but I've
cut out as much as I could to simplify it and also I wasn't happy with some
of the things he was doing.

  Although the build up of Virtual Address Space is slow, it doesn't seem to
stop. Due to the urgency of the problem, I'm having to CLD it. I don't know
whether this problem is directly due to the way XtDestroyWidget works or
whether it is the way it is being used in this case; maybe there is some
method to prevent this build up in VAS.

  It also seems that putting a time lag after destroying the widgets
helps reduce the problem.

  Does anybody have any ideas about preventing the problem. From reading
an Xtoolkit Programming manual the view was that X applications should not
run for very long anyway, I wonder if this is the only way to approach the
problem, ie. split the application up and fire up bits of it when needed ?

  Anyway any help on this problem would be greatly appreciated

Richard

PS. The programs are posted in the next replies 
2508.8detsroy.c - Customers versionSCOTMN::WOODEl VaqueroThu May 17 1990 12:03162
#include <stdio.h>
#include <ssdef.h>
#include <descrip>

#include <decw$include/Dwtwidget.h>
#include <decw$include/DECwDwtApplProg.h>

static XtCallbackProc create_cb();
void monitor_widget();
int libSetTimer();

Widget g_toplevel_widget,g_decw_top, g_widget_arr[100];

long next_widget = 0;
long cnt = 0;

Display *g_display = 0;

DRMHierarchy	g_hierarchy;

static DRMType *g_dummy_class;

static char *g_db_filename_vec[] = {"destroy.uid"};

static int g_db_filename_num = (sizeof g_db_filename_vec / sizeof g_db_filename_vec[0]);

static DRMRegisterArg g_reglist[] = {
		{"create_cb",(caddr_t)create_cb}
				};

static int g_reglist_num = (sizeof g_reglist / sizeof g_reglist [0]);

initialise(argc,argv)
unsigned int argc;
char *argv[];

{
if (DwtFetchWidget (g_hierarchy, "decw_top", g_toplevel_widget,&g_decw_top,
	&g_dummy_class) != DRMSuccess)
	printf("\nCan't fetch ADIS root window");

XtManageChild(g_decw_top);

g_display = DwtGetDisplay(g_decw_top);
XSynchronize(g_display,1);
}

main(argc,argv)
unsigned int argc;
char *argv[];

{
long status;

DwtInitializeDRM();

g_toplevel_widget = XtInitialize("DECW prob",
			"ADIS",
			NULL,
			0,
			&argc,
			argv);

status = DwtOpenHierarchy(g_db_filename_num,
			g_db_filename_vec,
			NULL,
			&g_hierarchy );

if (status != DRMSuccess)
	printf("\ncan't open hierarchy");

DwtRegisterDRMNames(g_reglist, g_reglist_num);

initialise(argc,argv);

XtRealizeWidget(g_toplevel_widget);

status = libSetTimer("0000 00:00:02.00",monitor_widget,0);

if (status != SS$_NORMAL)
	printf("\ncan't set timer");

XtMainLoop();

}

static XtCallbackProc create_cb (widget,tag,reason)
Widget widget;
char *tag;
DwtAnyCallbackStruct *reason;

{
g_widget_arr[next_widget++] = widget;
}


void monitor_widget()
{
long status,
	count,
	all_dead = 1,
	all_alive = 0;
XEvent event;

printf("\nmonitor nextWidget = %d, cnt = %d",next_widget,cnt);
if (next_widget ==10)
	{
	for (count=0; count<next_widget; count++)
		{
		all_dead &= g_widget_arr[count]->core.being_destroyed;
		all_alive |= g_widget_arr[count]->core.being_destroyed;
		}
	printf("\ndead = %d, alive = %d",all_alive,all_dead);
	cnt++;
	if (all_dead)
		{
		next_widget = 0;
		if (DwtFetchWidget(g_hierarchy,
					"WIND_1",
					g_decw_top,
					&g_widget_arr[0],
					&g_dummy_class
					) != DRMSuccess)
			printf("\ncan't fetch ADIS root window");
		XtManageChild(g_widget_arr[0]);
		}
	else if (!all_alive)
		{
		while  (XEventsQueued (g_display, QueuedAfterFlush))
			{
			XNextEvent(g_display, &event);
			}
		XtDestroyWidget(g_widget_arr[0]);
		}
	else
		{
		printf("\nWaiting");
		}
	}
status = libSetTimer("0000 00:00:00.01",monitor_widget,0);
if (status != SS$_NORMAL)
	printf("\ncan't set monitor timer");

}


int libSetTimer(timstr,proc,flag)
char *timstr;
void *proc;
int flag;

{
long int stat;
long bintim[2];
struct dsc$descriptor_s str_desc = { 16, DSC$K_DTYPE_T, DSC$K_CLASS_S,0};

str_desc.dsc$a_pointer = timstr;

stat = sys$bintim(&str_desc,&bintim);
stat = sys$setimr (flag,&bintim,proc,NULL,0);
return(stat);
}
2508.9destroy.c - my versionSCOTMN::WOODEl VaqueroThu May 17 1990 12:07116
#include <stdio.h>
#include <ssdef.h>
#include <descrip>

#include <decw$include/Dwtwidget.h>
#include <decw$include/DECwDwtApplProg.h>

static XtCallbackProc create_cb();
void monitor_widget();

Widget toplevel,decwTop, widgetArr[10];

long nextWidget = 0;
long cnt = 0;

Display *dpy = 0;

DRMHierarchy	hierarchy;

static DRMType *dummy_class;

static char *filename_vec[] = {"destroy.uid"};

static DRMRegisterArg reglist[] = {
		{"create_cb",(caddr_t)create_cb}
				};

static int reglist_num = 1;


static int filename_num = (sizeof filename_vec / sizeof filename_vec[0]);

main(argc,argv)
unsigned int argc;
char *argv[];

{
long status;

DwtInitializeDRM();

toplevel = XtInitialize("DECW prob",
			"ADIS",
			NULL,
			0,
			&argc,
			argv);

status = DwtOpenHierarchy(filename_num,
			filename_vec,
			NULL,
			&hierarchy );

DwtRegisterDRMNames(reglist, reglist_num);

if (status != DRMSuccess)
	printf("\ncan't open hierarchy");

if (DwtFetchWidget (hierarchy, "decw_top", toplevel,&decwTop, &dummy_class)
	!= DRMSuccess)
	printf("\ncan't fetch widget");

XtManageChild(decwTop);

dpy = DwtGetDisplay(decwTop);
XSynchronize(dpy,1);

XtRealizeWidget(toplevel);

for (;;)
	{
	monitor_widget();
	}

}

void monitor_widget()
{
long status;
XEvent event;
/*
printf("\ninside monitor - nextWidget = %d",nextWidget);
*/
if (nextWidget ==0)
	{
	nextWidget = 1;
	if (DwtFetchWidget(hierarchy,
				"WIND_1",
				decwTop,
				&widgetArr[0],
				&dummy_class
				) != DRMSuccess)
		printf("\ncan't fetch ADIS root window");
	XtManageChild(widgetArr[0]);
	}
else 
	{
	nextWidget = 0;
	while  (XEventsQueued (dpy, QueuedAfterFlush))
		{
		XNextEvent(dpy, &event);
		}
	XtDestroyWidget(widgetArr[0]);
	}

}

static XtCallbackProc create_cb (widget,tag,reason)
Widget widget;
char *tag;
DwtAnyCallbackStruct *reason;

{
widgetArr[nextWidget++] = widget;
}

2508.10destroy.uilSCOTMN::WOODEl VaqueroThu May 17 1990 12:09186
module decw_prob
  version = 'v1.0'
  names = case_sensitive

include file 'sys$library:decw$dwtdef.uil';
include file 'decw$include:dwtappl.uil';

procedure
  create_cb();


value
	toggle_b_label : compound_string('TOGGLE');



object
  decw_top : dialog_box {
    arguments { width = 500;
		height = 200;
		units = DwtPixelUnits;
		border_width = 0;
		 };
      controls {
        dialog_box  WIND_1;
      };
  };

object
  WIND_1 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_2;
      };
  };

object
  WIND_2 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_3;
      };
  };

object
  WIND_3 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_4;
      };
  };

object
  WIND_4 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_5;
      };
  };

object
  WIND_5 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_6;
      };
  };

object
  WIND_6 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_7;
      };
  };

object
  WIND_7 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_8;
      };
  };

object
  WIND_8 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_9;
      };
  };

object
  WIND_9 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
      controls {
        dialog_box  WIND_10;
      };
  };

object
  WIND_10 : dialog_box {
    arguments { x = 0;
		y = 0;
		width = 20;
		height = 20;
		border_width = 4;
		 };
	callbacks {
		create = procedure create_cb();
		};
  };

end module;
2508.11Almost forgot - versions!!SCOTMN::WOODEl VaqueroThu May 17 1990 12:359
My Workstation - VS3520
Customers - VS3100

VMS version 5.3-2

VAX C version 3.0

Richard