2017-07-21 47 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內部名單上的小部件的解除分配。

相關問題