【问题标题】:X Toolkit: heap is growing when recreating widgetsX Toolkit:重新创建小部件时堆正在增长
【发布时间】:2017-12-27 15:35:33
【问题描述】:

我试图了解为什么以下程序会泄漏内存。当我使用命令more /proc/<pid>/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();
        }
    }
}

【问题讨论】:

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

标签: c memory-leaks widget xlib motif


【解决方案1】:

我在我的代码中发现了错误:我必须添加一个 XtDispatchEvent(&event),它处理 destory 列表(Xt 中的一个内部列表)上的小部件的解除分配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-28
    • 1970-01-01
    • 2023-02-15
    • 1970-01-01
    • 2012-08-10
    • 2021-01-19
    • 2012-01-15
    • 1970-01-01
    相关资源
    最近更新 更多