1

I'm trying to understand why the following program is leaking memory. When I look at the heap size by using the command more /proc/<pid>/smaps, I can see that the heap is only growing. It seems that the XtDestroyWidget is not really freeing up the memory. I would be very grateful if somebody can tell me why this is happening and show me the right way of recreating widgets. Thanks in advance!

/* Compile on Solaris: cc widgets_mem.c -lXm -lXt -lX11 */
/* Compile on Linux: gcc -m32 widgets_mem.c -lXm -lXt -lX11 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysymdef.h>

#include <Xm/MainW.h>
#include <Xm/PushB.h>
#include <Xm/Form.h>


Widget      toplevel;
Widget      w_main;
Widget      w_bb;
Widget      w_button = NULL;

Window      root_win;
XtAppContext    app;
int     screen_number;
Display        *display = NULL;

void recreateWidgets ()
{
    printf ("recreating widgets\n");
    XtDestroyWidget (w_button);

    w_button = XtVaCreateManagedWidget (
    "button",
    xmPushButtonWidgetClass, w_bb,
    XmNfillOnArm, False,
    XmNhighlightThickness, 0,
    XmNborderWidth, 1,
    XmNmarginTop, 1,
    XmNmarginWidth, 2,
    XmNmarginHeight, 0,
    XmNwidth, 20,
    XmNheight, 10,
    XmNrecomputeSize, False,
    XmNalignment, XmALIGNMENT_CENTER,
    NULL);
}


void main (int argc, char **argv)
{
    XEvent  event;

    toplevel = XtVaAppInitialize (&app, "Mem leak test",
                  NULL, 0, &argc, argv, NULL, NULL);
    display = XtDisplay (toplevel);
    screen_number = DefaultScreen (display);
    root_win = RootWindow (display, screen_number);

    w_main = XtVaCreatePopupShell (
    "main", 
    topLevelShellWidgetClass, toplevel,
    XmNgeometry, "-0+0",
    XmNborderWidth, 0,
    XmNshadowThickness, 0,
    XmNminWidth, 1, 
    XmNmwmDecorations, 0,
    XmNmwmFunctions, 0,
    XmNwidth, 600,
    XmNheight, 200,
    NULL);

    w_bb = XtVaCreateManagedWidget (
    "",
    xmBulletinBoardWidgetClass, w_main,
    XmNborderWidth, 4,
    XmNshadowThickness, 0,
    XmNmarginWidth, 0,
    XmNmarginHeight, 0,
    XmNx, 0,
    XmNy, 0,
    XmNwidth, 500,
    XmNheight, 100,
    NULL);

    w_button = XtVaCreateManagedWidget (
    "button",
    xmPushButtonWidgetClass, w_bb,
    XmNfillOnArm, False,
    XmNhighlightThickness, 0,
    XmNborderWidth, 1,
    XmNmarginTop, 1,
    XmNmarginWidth, 2,
    XmNmarginHeight, 0,
    XmNwidth, 20,
    XmNheight, 10,
    XmNrecomputeSize, False,
    XmNalignment, XmALIGNMENT_CENTER,
    NULL);

    XtPopup (w_main, XtGrabNone);

    while (1)
    {
        XtAppNextEvent (app, &event);
        if (event.type == ButtonPress)
        {
            printf ("Button pressed, recreating widgets\n");
            recreateWidgets();
        }
    }
}
Gijsbert
  • 31
  • 2
  • 1
    Note that when memory is freed, it is not returned to the o/s; it is kept by the memory management system for reuse. If you free a widget, then the space it used may be used by the next widget that's created. So, it _could_ be that there isn't a problem. OTOH, if your program eventually crashes with a lack of memory, you do have leak that needs to be fixed. – Jonathan Leffler Jul 22 '17 at 15:56
  • On both Linux and Solaris, `void main()` is unconditionally wrong. The return type of `main()` is `int`. Only on Windows can you claim an exemption from that, and you're not on Windows. Half-way modern compilers would complain about that. You're not using enough compilation warnings. – Jonathan Leffler Jul 22 '17 at 15:57
  • 1
    If you think your program is leaking memory, I'd suggest you use either [valgrind](http://valgrind.org/), [dmalloc](http://dmalloc.com/) or [efence](http://elinux.org/Electric_Fence). – Bass Jul 25 '17 at 12:30
  • Thanks both for your help. I ran the program with valgrind, and it says "definitely lost: 0, indirectly lost: 0, possibly lost: 0", but "still reachable:" shows a value which is larger after recreating more widgets. Is this anything of concern? I recreated 100.000 widgets and noticed that after a while, the heap isn't growing anymore, so probably you are right, Jonathan. – Gijsbert Jul 28 '17 at 14:40

1 Answers1

0

I found the bug in my code: I had to add a XtDispatchEvent(&event), which handles the deallocating of the widgets which are on the destory list, an internal list in Xt.

Gijsbert
  • 31
  • 2