[Xcb] XPutImage to a pixmap is leaking memory

Guillaume Foliard guifo at wanadoo.fr
Tue Jun 1 05:34:08 PDT 2010


Hello,

The source file at the end of the message contains a simple program
which shows that a call to XPutImage to write a XImage to a pixmap
followed by a call to XCopyArea to copy
the whole pixmap to a window is leaking memory slowly
but surely.
However, calling the XPutImage to write the XImage directly to
the window is not leaking.
A quick analysis with valgrind has shown the leak is in XCB when calling XPutImage (test done under Fedora 13, the leak is also observed under F11).

Here is a rough copy/paste from the Valgrind output :

==10123== 15,984 bytes in 999 blocks are indirectly lost in loss record 21 of 25
==10123== at 0x4A0515D: malloc (vg_replace_malloc.c:195)
==10123== by 0x3B3860A6B1: ??? (in /usr/lib64/libxcb.so.1.1.0)
==10123== by 0x3B386088EC: ??? (in /usr/lib64/libxcb.so.1.1.0)
==10123== by 0x3B38608D86: ??? (in /usr/lib64/libxcb.so.1.1.0)
==10123== by 0x3B38609034: xcb_writev (in /usr/lib64/libxcb.so.1.1.0)
==10123== by 0x3B38A4D419: _XSend (in /usr/lib64/libX11.so.6.3.0)
==10123== by 0x3B38A3985C: ??? (in /usr/lib64/libX11.so.6.3.0)
==10123== by 0x3B38A38B50: ??? (in /usr/lib64/libX11.so.6.3.0)
==10123== by 0x3B38A39A3D: XPutImage (in /usr/lib64/libX11.so.6.3.0)
==10123== by 0x400B9D: main (put_image.c:76)

When run on an older Linux distribution without XCB a leak is also observed, but in libX11.

If you feel the need for further informations, please request them. Even though I have no knowledge of XCB/Xlib internals I'll do whatever I can to help to solve this problem.

Here is the source code :

---- begin ----

#include 
#include 
#include 
#include 
#include 

int main()
{
Display * display;
int screen_number, depth, bitmap_pad, status;
unsigned long white;
unsigned long black;
Window root, win;
GC gc;
Visual * visual;
XImage * image;
char * image_data;
unsigned int image_width, image_height, image_byte_size, i, j;
Pixmap pixmap;

image_width = 640;
image_height = 482;

display = XOpenDisplay (NULL);
if (! display)
{
return 1;
}

screen_number = DefaultScreen (display);
depth = DefaultDepth (display, screen_number);
visual = DefaultVisual (display, screen_number);
gc = DefaultGC (display, screen_number);
bitmap_pad = BitmapPad (display);
white = WhitePixel (display, screen_number);
black = BlackPixel (display, screen_number);
root = DefaultRootWindow (display);

win = XCreateSimpleWindow (display,
root,
50, 50,
800, 800,
0, black,
white);

XMapWindow (display, win);

image = XCreateImage (display, visual, depth, ZPixmap, 0, NULL, image_width, image_height, bitmap_pad, 0);

printf("depth : %d\nbitmap_pad : %d\nimage bpp : %d\n", depth, bitmap_pad, image->bits_per_pixel);

image_byte_size = image_width * image_height * image->bits_per_pixel / 8;
image_data = (char *) malloc (image_byte_size);
image->data = image_data;

// Fill image data with random data

for (i = 0; i < image_byte_size; i++)
{
image_data[i] = (char) (random() % 256);
}

pixmap = XCreatePixmap (display, root, image_width, image_height, depth);

for (j = 0; j < 1000; j++)
{
for (i = 0; i < image_byte_size; i++)
{
image_data[i] = (char) (random() % 256);
}

// The following does not leak
//XPutImage (display, win, gc, image, 0, 0, 50, 50, image_width, image_height);

// The following does leak
XPutImage (display, pixmap, gc, image, 0, 0, 0, 0, image_width, image_height);
XCopyArea (display, pixmap, win, gc, 0,0, image_width, image_height, 50, 50);
}

status = XDestroyImage (image);

// Comment the following line to allow valgrind to print interesting output
// status = XCloseDisplay (display);

return 0;
}

---- end ----

Guillaume




More information about the Xcb mailing list