Skip to content

[xlib] Fix memory leaks in xlib backend

Hodong requested to merge hodong/cairo:master into master

Hello.

There are memory leaks in the cairo xlib backend.

cc `pkg-config --cflags cairo x11` `pkg-config --libs cairo x11` cairo-xlib.c -o cairo-xlib

cairo-xlib.c

#include <X11/Xlib.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <math.h>
#include <stdio.h>

/* from https://www.cairographics.org/samples/arc/ */
void draw (cairo_t *cr)
{
  double xc = 128.0;
  double yc = 128.0;
  double radius = 100.0;
  double angle1 = 45.0  * (M_PI/180.0);  /* angles are specified */
  double angle2 = 180.0 * (M_PI/180.0);  /* in radians           */

  cairo_set_line_width (cr, 10.0);
  cairo_arc (cr, xc, yc, radius, angle1, angle2);
  cairo_stroke (cr);

  /* draw helping lines */
  cairo_set_source_rgba (cr, 1, 0.2, 0.2, 0.6);
  cairo_set_line_width (cr, 6.0);

  cairo_arc (cr, xc, yc, 10.0, 0, 2*M_PI);
  cairo_fill (cr);

  cairo_arc (cr, xc, yc, radius, angle1, angle1);
  cairo_line_to (cr, xc, yc);
  cairo_arc (cr, xc, yc, radius, angle2, angle2);
  cairo_line_to (cr, xc, yc);
  cairo_stroke (cr);
}

int main ()
{
  cairo_surface_t *surface;
  cairo_t         *cr;

  Display *display;
  Window   window;
  int screen;
  int width  = 250;
  int height = 250;
  Atom delete_window;

  display = XOpenDisplay (NULL);

  if (!display)
  {
    puts ("Can't open display");
    return 1;
  }

  screen  = DefaultScreen (display);
  window  = XCreateSimpleWindow (display, XDefaultRootWindow (display),
                                 0, 0, width, height,
                                 1, BlackPixel (display, 0), WhitePixel (display, 0));

  delete_window = XInternAtom (display, "WM_DELETE_WINDOW", False);
  XSetWMProtocols (display, window, &delete_window, 1);
  XSelectInput (display, window, ExposureMask);

  XMapWindow (display, window);

  surface = cairo_xlib_surface_create (display, window,
                                       DefaultVisual (display, screen), width, height);
  cr = cairo_create (surface);

  while (1)
  {
    XEvent event;
    XNextEvent (display, &event);

    if (event.type == Expose)
    {
      draw (cr);
    }
    else if (event.type == ClientMessage &&
             event.xclient.data.l[0] == delete_window)
      break;
  }

  cairo_destroy (cr);
  cairo_surface_destroy (surface);

  XDestroyWindow (display, window);
  XCloseDisplay  (display);

  return 0;
}
% valgrind --leak-check=full ./cairo-xlib
==86579== Memcheck, a memory error detector
==86579== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==86579== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==86579== Command: ./cairo-xlib
==86579==
==86579==
==86579== HEAP SUMMARY:
==86579==     in use at exit: 16,040 bytes in 14 blocks
==86579==   total heap usage: 239 allocs, 225 frees, 125,320 bytes allocated
==86579==
==86579== 360 bytes in 1 blocks are definitely lost in loss record 5 of 14
==86579==    at 0x484C8A4: malloc (in /usr/local/libexec/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==86579==    by 0x4941A46: source (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x49419C4: color_source (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x493FFFC: _cairo_xlib_source_create_for_pattern (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x491BA62: clip_and_composite (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x491A958: _cairo_traps_compositor_stroke (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x48BCBA6: _cairo_compositor_stroke (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x49449BA: _cairo_xlib_surface_stroke (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x4914363: _cairo_surface_stroke (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x48C4F60: _cairo_gstate_stroke (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x48BFBBC: _cairo_default_context_stroke (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x4923059: cairo_stroke (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==
==86579== 360 bytes in 1 blocks are definitely lost in loss record 6 of 14
==86579==    at 0x484C8A4: malloc (in /usr/local/libexec/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==86579==    by 0x4941A46: source (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x49419C4: color_source (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x4940294: _cairo_xlib_source_create_for_pattern (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x491BA62: clip_and_composite (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x491B77B: clip_and_composite_polygon (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x491A601: _cairo_traps_compositor_fill (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x48BCCA6: _cairo_compositor_fill (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x4944AF2: _cairo_xlib_surface_fill (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x4914164: _cairo_surface_fill (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x48C53EF: _cairo_gstate_fill (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==    by 0x48BFC6C: _cairo_default_context_fill (in /usr/local/lib/libcairo.so.2.11704.0)
==86579==
==86579== LEAK SUMMARY:
==86579==    definitely lost: 720 bytes in 2 blocks
==86579==    indirectly lost: 0 bytes in 0 blocks
==86579==      possibly lost: 0 bytes in 0 blocks
==86579==    still reachable: 15,320 bytes in 12 blocks
==86579==         suppressed: 0 bytes in 0 blocks
==86579== Reachable blocks (those to which a pointer was found) are not shown.
==86579== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==86579==
==86579== For lists of detected and suppressed errors, rerun with: -s
==86579== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

This patch fixes these memory leaks.

Edited by Hodong

Merge request reports