XForms: Memory Leak with Statically Inited Menus

Ivan Powis (pczip@chemistry.nottingham.ac.uk)
Mon, 12 Jan 1998 11:39:32 GMT

To subscribers of the xforms list from Ivan Powis <pczip@chemistry.nottingham.ac.uk> :

I have encountered a memory leak when using statically initialised
menus (ie when using fl_set_menu_entries() and an array of FL_PUP_ENTRY
structures) which I think is an internal library bug. I have an app
which creates many temporary forms using such code. Each form is
subsequently killed off with a sequence
fl_hide_form(ob->form);
fl_free_form(ob->form);
free(ob->form->fdui);
which unless I've misread something should free all resources
associated with the form. Even so after the 32nd form I get the
following error:

In defpup [xpopup.c 169] Exceeded FL_MAXPUP (32)
Please check for leaks. Current allocated menus are:
0: Notitle
1: Notitle
[ ... etc...]
31: Notitle

with malfunctioning menus on the latest forms.

I've knocked up a little demo to indicate the problem (below) - just
keep using the menu on the subform to create a new subform and destroy
the current one and failure will result after the 32nd. Using instead
ordinary initialisation by fl_set_menu() [define DINIT when compiling]
does not give this problem, and behaves seemingly ok.

forms 0.88 HP/UX

Ivan

ps TC thanks for picking up my suggestions for a polar mode for xyplot,
I look forward to seeing it in a future release.

/*------------------------------------------------------------------------*/
#include <stdio.h>
#include "forms.h"
#include "demo.h"

/* Globals */
static int nforms;
FD_one *fd_one;

static int subform_close(FL_FORM *frm, void *datp);

int main(int argc, char *argv[])
{

fl_initialize(&argc, argv, 0, 0, 0);
fd_one = create_form_one();
#ifdef DINIT
printf("Dynamic menu initialization\n");
#else
printf("Static menu initialization\n");
#endif
/* show the first form */
fl_show_form(fd_one->one,FL_PLACE_CENTERFREE,FL_FULLBORDER,"one");
fl_do_forms();
}

/**********************************************/
/* callbacks and freeobj handles for form one */
/**********************************************/

void c_pb_cb(FL_OBJECT *ob, long data)
/* create a subform from the main form*/
{
FD_two *fd;
char buff[100];

nforms++;
sprintf(buff,"Nforms=%d",nforms);
fl_set_object_label(fd_one->text,buff); /* count shown on main form */

fd = create_form_two();
#ifdef DINIT
fl_set_menu(fd->menu,"Create | Exit");
#endif
fl_set_form_atclose(fd->two, subform_close, NULL);
fl_show_form(fd->two,FL_PLACE_CENTERFREE,FL_FULLBORDER,buff);
}

void exit_pb_cb(FL_OBJECT *ob, long data)
{
exit(0);
}

/**********************************************/
/* callbacks and freeobj handles for form two */
/**********************************************/

void menu_cb(FL_OBJECT *ob, long data)
{
FD_two *fd;
char buff[100];
int i=fl_get_menu(ob);

switch (i){
case 1: /* create new formFIT */
nforms++;
sprintf(buff,"Nforms=%d",nforms);
fl_set_object_label(fd_one->text,buff); /* count shown on main form */

fd = create_form_two();
#ifdef DINIT
fl_set_menu(fd->menu,"Create | Exit");
#endif
fl_set_form_atclose(fd->two, subform_close, NULL);
fl_show_form(fd->two,FL_PLACE_CENTERFREE,FL_FULLBORDER,buff);
case 2: /* deliberate fall through to kill off form */
/*This should (?) free all memory allocated to form then kill it*/
fl_hide_form(ob->form);
fl_free_form(ob->form);
free(ob->form->fdui);
break;
default:
fprintf(stderr,"Unknown menu item\n");
break;
}
return;
}

/*
Close the Form Function
- registered to stop WM form closure terminating full application
*/
static int subform_close(FL_FORM *frm, void *datp)
{
return FL_OK;
}

/* Form definition file generated with fdesign. */

FD_one *create_form_one(void)
{
FL_OBJECT *obj;
FD_one *fdui = (FD_one *) fl_calloc(1, sizeof(*fdui));

fdui->one = fl_bgn_form(FL_NO_BOX, 320, 250);
obj = fl_add_box(FL_UP_BOX,0,0,320,250,"");
fdui->text = obj = fl_add_text(FL_NORMAL_TEXT,30,20,260,50,"MAIN FORM");
fl_set_object_lsize(obj,FL_LARGE_SIZE);
fl_set_object_lalign(obj,FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
obj = fl_add_button(FL_NORMAL_BUTTON,30,80,220,70,"Create SubForm");
fl_set_object_lsize(obj,FL_LARGE_SIZE);
fl_set_object_callback(obj,c_pb_cb,0);
obj = fl_add_button(FL_NORMAL_BUTTON,30,160,220,70,"Exit");
fl_set_object_lsize(obj,FL_LARGE_SIZE);
fl_set_object_callback(obj,exit_pb_cb,0);
fl_end_form();

fdui->one->fdui = fdui;

return fdui;
}
/*---------------------------------------*/

#ifndef DINIT
static FL_PUP_ENTRY fdmenu_Menu0[] =
{
/* itemtext callback shortcut mode */
{ "Create New SubForm", 0, "", FL_PUP_NONE},
{ "Exit", 0, "", FL_PUP_NONE},
{0}
};
#endif

FD_two *create_form_two(void)
{
FL_OBJECT *obj;
FD_two *fdui = (FD_two *) fl_calloc(1, sizeof(*fdui));

fdui->two = fl_bgn_form(FL_NO_BOX, 260, 140);
obj = fl_add_box(FL_UP_BOX,0,0,260,140,"");
fdui->menu = obj = fl_add_menu(FL_PULLDOWN_MENU,10,10,150,60,"Menu");
fl_set_object_boxtype(obj,FL_UP_BOX);
fl_set_object_lsize(obj,FL_MEDIUM_SIZE);
fl_set_object_callback(obj,menu_cb,0);
#ifndef DINIT
fl_set_menu_entries(obj, fdmenu_Menu0);
#endif
fl_end_form();

fdui->two->fdui = fdui;

return fdui;
}
/*---------------------------------------*/

--
-------------------------------------------------------------------------+
    ___  ___/   _  __ /  Ivan Powis                TEL: +44-115-951-3467 |
        /         /   /  Department of Chemistry   FAX: +44-115-951-3562 |
       /         /  _/   University of Nottingham                        |
      /         ___/     Nottingham NG7 2RD                              |
     /         /         UK                                              |
    /         /                      pczip@chem.nott.ac.uk               | 
_______/  ____/                      http://www.chem.nott.ac.uk/IP.html  |
-------------------------------------------------------------------------+

_________________________________________________ To unsubscribe, send the message "unsubscribe" to xforms-request@bob.usuf2.usuhs.mil or see http://bob.usuf2.usuhs.mil/mailserv/xforms.html Xforms Home Page: http://bloch.phys.uwm.edu/xforms List Archive: http://bob.usuf2.usuhs.mil/mailserv/list-archives/