C X工具包:当重新创建小部件时,堆正在增长

C X工具包:当重新创建小部件时,堆正在增长,c,memory-leaks,widget,xlib,motif,C,Memory Leaks,Widget,Xlib,Motif,我试图理解为什么下面的程序会泄漏内存。当我使用命令more/proc//smaps查看堆大小时,我可以看到堆只是在增长。似乎XtDestroyWidget并没有真正释放内存。如果有人能告诉我为什么会发生这种情况,并告诉我重新创建小部件的正确方法,我将非常感激。 提前谢谢 /* Compile on Solaris: cc widgets_mem.c -lXm -lXt -lX11 */ /* Compile on Linux: gcc -m32 widgets_mem.c -lXm -lXt -

我试图理解为什么下面的程序会泄漏内存。当我使用命令
more/proc//smaps
查看堆大小时,我可以看到堆只是在增长。似乎XtDestroyWidget并没有真正释放内存。如果有人能告诉我为什么会发生这种情况,并告诉我重新创建小部件的正确方法,我将非常感激。 提前谢谢

/* 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();
        }
    }
}
/*在Solaris上编译:cc widgets_mem.c-lXm-lXt-lX11*/
/*在Linux上编译:gcc-m32 widgets_mem.c-lXm-lXt-lX11*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
小部件顶层;
小工具w_main;
小工具w_bb;
小部件w_按钮=空;
窗口根!;
XtAppContext应用程序;
int屏幕编号;
Display*Display=NULL;
void重新创建小部件()
{
printf(“重新创建小部件\n”);
小部件(w_按钮);
w_button=XtVaCreateManagedWidget(
“按钮”,
xmPushButtonWidgetClass,w_bb,
XmNfillOnArm,False,
XmNhighlightThickness,0,
XmNborderWidth,1,
XmNmarginTop,1,
XmNmarginWidth,2,
XmNmarginHeight,0,
XmNwidth,20,
XmNheight,10岁,
xmnRecomuteSize,False,
XmNalignment,XMU中心,
无效);
}
void main(整型argc,字符**argv)
{
XEvent事件;
toplevel=XtVaAppInitialize(&app,“内存泄漏测试”,
NULL,0,&argc,argv,NULL,NULL);
显示=XtDisplay(顶级);
屏幕号=默认屏幕(显示);
root\u win=root窗口(显示,屏幕编号);
w_main=XtVaCreatePopupShell(
“主要”,
topLevelShellWidgetClass,toplevel,
xNgeometry,“-0+0”,
XmNborderWidth,0,
XmNshadowThickness,0,
XmNminWidth,1,
xmnmwm,0,
xmnmwmf函数,0,
XmNwidth,600,
XmNheight,200,
无效);
w_bb=XtVaCreateManagedWidget(
"",
xmBulletinBoardWidgetClass,w_main,
XmNborderWidth,4,
XmNshadowThickness,0,
XmNmarginWidth,0,
XmNmarginHeight,0,
XmNx,0,
XmNy,0,
XmNwidth,500,
XmNheight,100,
无效);
w_button=XtVaCreateManagedWidget(
“按钮”,
xmPushButtonWidgetClass,w_bb,
XmNfillOnArm,False,
XmNhighlightThickness,0,
XmNborderWidth,1,
XmNmarginTop,1,
XmNmarginWidth,2,
XmNmarginHeight,0,
XmNwidth,20,
XmNheight,10岁,
xmnRecomuteSize,False,
XmNalignment,XMU中心,
无效);
XtPopup(w_main,XtGrabNone);
而(1)
{
XtAppNextEvent(应用程序和事件);
如果(event.type==ButtonPress)
{
printf(“按下按钮,重新创建小部件\n”);
重新创建Widgets();
}
}
}

我在代码中发现了错误:我必须添加一个XtDispatchEvent(&event),它处理Destrory列表中小部件的释放,一个Xt中的内部列表。

我在代码中发现了错误:我必须添加一个XtDispatchEvent(&event),它处理Destrory列表中小部件的释放,Xt中的一个内部列表。

请注意,当释放内存时,它不会返回到o/s;它由内存管理系统保存以供重用。如果您释放一个小部件,那么它使用的空间可能会被创建的下一个小部件使用。所以,可能没有问题。OTOH,如果您的程序最终因内存不足而崩溃,那么您确实存在需要修复的漏洞。在Linux和Solaris上,
void main()
是无条件错误的。
main()
的返回类型是
int
。只有在Windows上,您才能申请豁免,而您不在Windows上。现代编译器会对此半途而废。您没有使用足够的编译警告。如果您认为您的程序正在泄漏内存,我建议您使用或。谢谢您的帮助。我用valgrind运行了这个程序,它说“肯定丢失了:0,间接丢失了:0,可能丢失了:0”,但“仍然可以访问:”显示了一个在重新创建更多小部件后更大的值。这有什么关系吗?我重新创建了100.000个小部件,并注意到过了一段时间,堆不再增长,所以你可能是对的,Jonathan;它由内存管理系统保存以供重用。如果您释放一个小部件,那么它使用的空间可能会被创建的下一个小部件使用。所以,可能没有问题。OTOH,如果您的程序最终因内存不足而崩溃,那么您确实存在需要修复的漏洞。在Linux和Solaris上,
void main()
是无条件错误的。
main()
的返回类型是
int
。只有在Windows上,您才能申请豁免,而您不在Windows上。现代编译器会对此半途而废。您没有使用足够的编译警告。如果您认为您的程序正在泄漏内存,我建议您使用或。谢谢您的帮助。我用valgrind运行了这个程序,它说“肯定丢失了:0,间接丢失了:0,可能丢失了:0”,但“仍然可以访问:”显示了一个在重新创建更多小部件后更大的值。这有什么关系吗?我重新创建了10万个小部件,并注意到过了一段时间,小部件的数量不再增长,所以你可能是对的,乔纳森。