在同一应用程序进程中使用XFT字体第二次使用新的显示连接绘制文本时崩溃

时间:2014-07-20 13:15:20

标签: fonts x11 xorg

我试图在我的应用程序中使用XFT,但是第二次尝试在同一进程中使用新的显示连接绘制文本时崩溃了。以下是我的用例的简化版本。

while true
do
    OpenDisplay
    LoadFont
    Draw Text
    Close Font   
    Close Display
end

我在一些论坛上看到XCloseDisplay也会关闭字体,但是当我尝试加载多个字体时,我注意到了内存泄漏。

我试图调试这个问题,这些是我的观察,

  1. 评论XftDrawText,崩溃消失
  2. 评论XftFontClose,崩溃消失但内存泄漏
  3. 以下是我用来重现此代码的代码。任何帮助将不胜感激。

    #include <X11/Xlib.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <cstring>
    #include <iostream>
    #include <X11/Xft/Xft.h>
    
    using namespace std;
    
    const char fontNames[5][50] = { "helvetica", "arial", "courier", "times", "utopia" };
    int sizes[5] = {10, 20, 30, 40, 50};
    int numFonts = 5;
    
    void TestXft(Display* display, Window& win, GC& gc, const char *fontName, int size);
    
    Window create_simple_window(Display* display, int width, int height, int x, int y)
    {
        int screen_num = DefaultScreen(display);
        int win_border_width = 2;
        Window win;
        win = XCreateSimpleWindow(display, RootWindow(display, screen_num), x, y,
                width, height, win_border_width,
                BlackPixel(display, screen_num),
                WhitePixel(display, screen_num));
    
        XMapWindow(display, win);
    
        XFlush(display);
    
        return win;
    }
    
    GC create_gc(Display* display, Window win)
    {
        GC gc;
        unsigned long valuemask = 0;
        XGCValues values;
    
        gc = XCreateGC(display, win, valuemask, &values);
    
        if (gc < 0)
        {
            fprintf(stderr, "XCreateGC: \n");
        }
        return gc;
    }
    
    int main(int argc, char* argv[])
    {
        int screen_num;
        Window win;
        unsigned int display_width, display_height;
        GC gc;
        unsigned long count = 0;
    
        while(true)
        {       
            cout << "\nIteration: " << ++count << endl;
    
            Display* display = XOpenDisplay(NULL);
            if (display == NULL)
            {
                printf("Cannot connect to X server\n");
                exit(1);
            }
    
            screen_num = DefaultScreen(display);
            display_width = 500;
            display_height = 500;
    
            win = create_simple_window(display, display_width, display_height, 0, 0);
            XMapWindow(display, win);
    
            XMoveWindow(display, win, 1000, 600);
    
            gc = create_gc(display, win);
    
            for(int i = 0; i < numFonts; i++)
            {
                TestXft(display, win, gc, fontNames[i], sizes[i]);
            }
    
            XUnmapWindow(display, win);
            XFreeGC(display, gc);
            XSync(display, false);
            XCloseDisplay(display);
        }
        return 0;
    }
    
    void TestXft(Display* display, Window& win, GC& gc, const char *fontName, int size)
    {
        XftFont      *font = NULL;
        XftDraw      *xftdraw = NULL;
        XRenderColor xrcolor;
        XftColor     xftcolor;
        font = NULL;
    
        Colormap colormap = XCreateColormap(display, win, DefaultVisual(display, DefaultScreen(display)), AllocNone);
    
        font = XftFontOpen(display, DefaultScreen(display), XFT_FAMILY, XftTypeString, fontName,
                                    XFT_SIZE, XftTypeDouble, (double) size,
                                    XFT_SCALE, XftTypeDouble, 2.0,
                                    NULL);
        if (!font)
        {
            printf("Font not Found.\n");
            return;
        }
    
        xftdraw = XftDrawCreate(display, win, DefaultVisual(display,0), colormap);
    
        xrcolor.red = 65535;
        xrcolor.green= 0;
        xrcolor.blue = 0;
        xrcolor.alpha= 65535;
        XftColorAllocValue(display, DefaultVisual(display,0), colormap, &xrcolor, &xftcolor);
    
        const char *text = "RCB...RCB...RCB";
        XftDrawString8(xftdraw, &xftcolor, font, 200, 300 , (XftChar8 *) text, strlen(text));
    
        XftColorFree(display, DefaultVisual(display,0), colormap, &xftcolor);
        XftDrawDestroy(xftdraw);
        XftFontClose(display, font);
        XFreeColormap(display, colormap);
    }
    

1 个答案:

答案 0 :(得分:0)

这是Xft库中的一个错误,它阻止它在多次打开和关闭显示时有用。

XOpenDisplayXCloseDisplay移出循环,添加对XDestroyWindow的调用,它会起作用。