2017-07-21 57 views
1

我想了解为什么下面的程序正在泄漏内存。当我通过使用命令more /proc/<pid>/smaps查看堆大小时,我可以看到堆只在增长。看来XtDestroyWidget并没有真正释放内存。如果有人能告诉我为什么会发生这种情况,并告诉我重新创建小部件的正确方法,我将非常感激。 在此先感谢!X工具包:重新创建小部件时堆正在增长

/* 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(); 
     } 
    } 
} 
+1

请注意,当内存被释放时,它不会返回到o/s;它由内存管理系统保存以供重用。如果你释放一个小部件,那么它使用的空间可能会被创建的下一个小部件使用。所以,它可能是因为没有问题。 OTOH,如果你的程序最终因内存不足而崩溃,你确实有泄漏需要修复。 –

+0

在Linux和Solaris上,void main()都是无条件错误的。 main()的返回类型是int。只有在Windows上,您才能从中获得豁免权,而您不在Windows上。现代中间编译器会抱怨这一点。您没有使用足够的编译警告。 –

+1

如果你认为你的程序在泄漏内存,我建议你使用[valgrind](http://valgrind.org/),[dmalloc](http://dmalloc.com/)或[efence](http ://elinux.org/Electric_Fence)。 – Bass

回答

0

,我发现我的代码中的bug:我不得不添加一个XtDispatchEvent(&事件),它处理这是destory名单中,XT内部名单上的小部件的解除分配。