2015-11-22 3 views
0

Ceci est ma première expérience avec Cairo. Je crée la surface en utilisant cette fonction:La mémoire fuit avec Cairo

//This function should give us a new x11 surface to draw on. 
cairo_surface_t *create_x11_surface(Display *d, int *x, int *y) { 
    Drawable da; 
    int screen; 
    cairo_surface_t *sfc; 
    Screen *scr; 

    screen = DefaultScreen(d); 
    scr = DefaultScreenOfDisplay(d); 
    if (!*x || !*y) { 
     *x = WidthOfScreen(scr)/2; 
     *y = HeightOfScreen(scr)/2; 
     da = 
      XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, *x, *y, 0, 0, 0); 
    } else 
     da = 
      XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, *x, *y, 0, 0, 0); 

    XSelectInput(d, da, ButtonPressMask | ButtonReleaseMask | KeyPressMask | 
          ButtonMotionMask | StructureNotifyMask); 

    // http://www.lemoda.net/c/xlib-wmclose/index.html 
    /* "wm_delete_window" is the Atom which corresponds to the delete 
      window message sent by the window manager. */ 
    Atom wm_delete_window; 
    wm_delete_window = XInternAtom(d, "WM_DELETE_WINDOW", False); 
    /* Set up the window manager protocols. The third argument here is 
     meant to be an array, and the fourth argument is the size of 
     the array. */ 

    XSetWMProtocols(d, da, &wm_delete_window, 1); 
    XMapWindow(d, da); 

    sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), *x, *y); 

    return sfc; 
} 

Mon main() consiste à créer un objet Drawer et appelant sa méthode run. Drawer est défini comme suit (un peu simplifié, le paramètre de modèle utilisé est non représenté):

struct Drawer { 
    Drawer() { 
     d = XOpenDisplay(NULL); 
     if (d == NULL) { 
      fprintf(stderr, "Failed to open display\n"); 
      exit(-1); 
     } 
     // create a new cairo surface in an x11 window as well as a cairo_t* to 
     // draw on the x11 window with. 
     int x=500, y=500; 
     surface = create_x11_surface(d, &x, &y); 
     cr = cairo_create(surface); 
    } 

    // https://stackoverflow.com/a/19308254/2725810 
    ~Drawer() { 
     cairo_destroy(cr); 
     cairo_surface_destroy(surface); 
     XCloseDisplay(d); 
    } 

    // Returns true if need to continue or false if quiting 
    bool processEvents() { 
     XEvent e; 

     if (XPending(cairo_xlib_surface_get_display(surface))) { 
      XNextEvent(cairo_xlib_surface_get_display(surface), &e); 
      switch (e.type) { 
      case ButtonPress: 
       drag_start_x = e.xbutton.x; 
       drag_start_y = e.xbutton.y; 
       break; 
      case ButtonRelease: 
       last_delta_x = 0; 
       last_delta_y = 0; 
       break; 
      case MotionNotify: 
       // http://cairographics.org/manual/cairo-Transformations.html#cairo-translate 
       cairo_translate(cr, e.xmotion.x - drag_start_x - last_delta_x, 
           e.xmotion.y - drag_start_y - last_delta_y); 
       last_delta_x = e.xmotion.x - drag_start_x; 
       last_delta_y = e.xmotion.y - drag_start_y; 
       break; 
      case ConfigureNotify: 
       cairo_xlib_surface_set_size(surface, e.xconfigure.width, 
              e.xconfigure.height); 
       break; 
      case ClientMessage: 
       return false; 
      default: 
       fprintf(stderr, "Dropping unhandled XEevent.type = %d.\n", 
         e.type); 
      } 
     } 
     return true; 
    } 

    void draw() { 
     cairo_push_group(cr); 

     // Clear the background 
     cairo_set_source_rgb(cr, 0, 0, 0); 
     cairo_paint(cr); 

     cairo_set_source_rgb(cr, 0, 1, 0); 
     cairo_move_to(cr, 0, 0); 
     cairo_line_to(cr, 256, 256); 
     cairo_move_to(cr, 256, 0); 
     cairo_line_to(cr, 0, 256); 
     cairo_set_line_width(cr, 10.0); 
     cairo_stroke(cr); 

     cairo_pop_group_to_source(cr); 
     cairo_paint(cr); 
     cairo_surface_flush(surface); 
     XFlush(d); 
    } 

    void run() { 
     while (1) { 
      if (!processEvents()) break; 
      draw(); 
      sleep(0.1); 
     } 
    } 

private: 
    Display *d; 
    cairo_surface_t* surface; 
    cairo_t* cr; 
    int last_delta_x = 0, last_delta_y = 0; 
    int drag_start_x, drag_start_y; 
}; 

Le programme est compilé avec la version 4.8.2 gcc.

valgrind signale les fuites de mémoire et indique les appels à cairo_stroke et les autres fonctions Cairo en tant que causes de la fuite. Il dit aussi que de la mémoire ne reste pas libérée quand le programme se termine malgré le fait que le destructeur de Drawer soit appelé. Voici la sortie de valgrind:

==6897== Memcheck, a memory error detector 
==6897== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==6897== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info 
==6897== Command: ./Test 
==6897== 
Dropping unhandled XEevent.type = 21. 
Dropping unhandled XEevent.type = 19. 
Dropping unhandled XEevent.type = 65. 
==6897== 
==6897== HEAP SUMMARY: 
==6897==  in use at exit: 12,696 bytes in 12 blocks 
==6897== total heap usage: 19,039 allocs, 19,027 frees, 8,088,426 bytes allocated 
==6897== 
==6897== 72 bytes in 1 blocks are still reachable in loss record 1 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x4E59F7C: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5B5B9: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5BAE5: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5CAB0: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5D87D: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4EA2050: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4EA3142: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5FECF: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E57F01: cairo_push_group_with_content (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x40590D: Drawer<NoGraph<StateNeighbor<Pancake, true> > >::draw() (Drawer.h:115) 
==6897== by 0x403A7A: Drawer<NoGraph<StateNeighbor<Pancake, true> > >::run() (Drawer.h:138) 
==6897== 
==6897== 72 bytes in 1 blocks are still reachable in loss record 2 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x4E59F7C: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5B5B9: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5BAE5: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5CDB2: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4EB4DE3: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5DA63: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4ECEA3C: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4EA2411: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E651E1: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5F168: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E58994: cairo_stroke (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== 
==6897== 160 bytes in 1 blocks are still reachable in loss record 3 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x4E850BC: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E851BC: cairo_pattern_create_rgba (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E6028A: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E57FC9: cairo_set_source_rgb (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x405959: Drawer<NoGraph<StateNeighbor<Pancake, true> > >::draw() (Drawer.h:121) 
==6897== by 0x403A7A: Drawer<NoGraph<StateNeighbor<Pancake, true> > >::run() (Drawer.h:138) 
==6897== by 0x402269: main (Test.cpp:48) 
==6897== 
==6897== 256 bytes in 2 blocks are still reachable in loss record 4 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x4E8529A: cairo_pattern_create_for_surface (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5FD7F: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E57F48: cairo_pop_group (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5809D: cairo_pop_group_to_source (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x405A38: Drawer<NoGraph<StateNeighbor<Pancake, true> > >::draw() (Drawer.h:129) 
==6897== by 0x403A7A: Drawer<NoGraph<StateNeighbor<Pancake, true> > >::run() (Drawer.h:138) 
==6897== by 0x402269: main (Test.cpp:48) 
==6897== 
==6897== 352 bytes in 1 blocks are definitely lost in loss record 5 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x4ECC831: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4ECC933: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4ECD497: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4EB3922: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4EB4E32: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5DA63: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4ECEA3C: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4EA2411: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E651E1: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E5F168: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x4E58994: cairo_stroke (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== 
==6897== 1,424 bytes in 1 blocks are still reachable in loss record 6 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x4E604E7: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==6897== by 0x403A04: Drawer<NoGraph<StateNeighbor<Pancake, true> > >::Drawer(NoGraph<StateNeighbor<Pancake, true> > const&) (Drawer.h:66) 
==6897== by 0x40225D: main (Test.cpp:47) 
==6897== 
==6897== 2,072 bytes in 1 blocks are still reachable in loss record 7 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FCBACE: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FCD585: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==6897== by 0x4010222: _dl_init (dl-init.c:36) 
==6897== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==6897== 
==6897== 2,072 bytes in 1 blocks are still reachable in loss record 8 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FCA61F: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FCD5A0: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==6897== by 0x4010222: _dl_init (dl-init.c:36) 
==6897== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==6897== 
==6897== 2,072 bytes in 1 blocks are still reachable in loss record 9 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FE5A8F: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FBC1A5: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FCD5AB: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==6897== by 0x4010222: _dl_init (dl-init.c:36) 
==6897== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==6897== 
==6897== 2,072 bytes in 1 blocks are still reachable in loss record 10 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x60053CF: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FCD5AB: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==6897== by 0x4010222: _dl_init (dl-init.c:36) 
==6897== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==6897== 
==6897== 2,072 bytes in 1 blocks are still reachable in loss record 11 of 11 
==6897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6897== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5FCFCBF: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==6897== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==6897== by 0x4010222: _dl_init (dl-init.c:36) 
==6897== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==6897== 
==6897== LEAK SUMMARY: 
==6897== definitely lost: 352 bytes in 1 blocks 
==6897== indirectly lost: 0 bytes in 0 blocks 
==6897==  possibly lost: 0 bytes in 0 blocks 
==6897== still reachable: 12,344 bytes in 11 blocks 
==6897==   suppressed: 0 bytes in 0 blocks 
==6897== 
==6897== For counts of detected and suppressed errors, rerun with: -v 
==6897== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 

Qu'est-ce que je fais pas?

MISE À JOUR: Après avoir inséré un appel à cairo_debug_reset_static_data() du destructor comme suggéré here, la sortie de valgrind est devenu un peu plus courte:

==7310== Memcheck, a memory error detector 
==7310== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==7310== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info 
==7310== Command: ./Test 
==7310== 
Dropping unhandled XEevent.type = 21. 
Dropping unhandled XEevent.type = 19. 
Dropping unhandled XEevent.type = 65. 
==7310== 
==7310== HEAP SUMMARY: 
==7310==  in use at exit: 10,712 bytes in 6 blocks 
==7310== total heap usage: 29,352 allocs, 29,346 frees, 12,459,938 bytes allocated 
==7310== 
==7310== 352 bytes in 1 blocks are definitely lost in loss record 1 of 6 
==7310== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7310== by 0x4ECC831: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4ECC933: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4ECD497: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4EB3922: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4EB4E32: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4E5DA63: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4ECEA3C: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4EA2411: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4E651E1: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4E5F168: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== by 0x4E58994: cairo_stroke (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0) 
==7310== 
==7310== 2,072 bytes in 1 blocks are still reachable in loss record 2 of 6 
==7310== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7310== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FCBACE: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FCD585: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==7310== by 0x4010222: _dl_init (dl-init.c:36) 
==7310== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==7310== 
==7310== 2,072 bytes in 1 blocks are still reachable in loss record 3 of 6 
==7310== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7310== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FCA61F: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FCD5A0: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==7310== by 0x4010222: _dl_init (dl-init.c:36) 
==7310== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==7310== 
==7310== 2,072 bytes in 1 blocks are still reachable in loss record 4 of 6 
==7310== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7310== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FE5A8F: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FBC1A5: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FCD5AB: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==7310== by 0x4010222: _dl_init (dl-init.c:36) 
==7310== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==7310== 
==7310== 2,072 bytes in 1 blocks are still reachable in loss record 5 of 6 
==7310== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7310== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x60053CF: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FCD5AB: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==7310== by 0x4010222: _dl_init (dl-init.c:36) 
==7310== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==7310== 
==7310== 2,072 bytes in 1 blocks are still reachable in loss record 6 of 6 
==7310== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7310== by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5FCFCBF: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) 
==7310== by 0x4010139: call_init.part.0 (dl-init.c:78) 
==7310== by 0x4010222: _dl_init (dl-init.c:36) 
==7310== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==7310== 
==7310== LEAK SUMMARY: 
==7310== definitely lost: 352 bytes in 1 blocks 
==7310== indirectly lost: 0 bytes in 0 blocks 
==7310==  possibly lost: 0 bytes in 0 blocks 
==7310== still reachable: 10,360 bytes in 5 blocks 
==7310==   suppressed: 0 bytes in 0 blocks 
==7310== 
==7310== For counts of detected and suppressed errors, rerun with: -v 
==7310== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 

BTW, pourquoi ne pas valgrind montrer la pleine callstack pour les perdus enregistrer et s'arrête à cairo_stroke à la place? Mon programme est compilé avec gcc avec le drapeau -g ...

MISE À JOUR: Comme demandé dans les commentaires, voici le tout exemple de travail:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <cairo-xlib.h> 
#include <X11/Xlib.h> 
#include <X11/Xatom.h> 
#include <X11/Xutil.h> 
#include <unistd.h> 

//This function should give us a new x11 surface to draw on. 
cairo_surface_t *create_x11_surface(Display *d, int *x, int *y) { 
    Drawable da; 
    int screen; 
    cairo_surface_t *sfc; 
    Screen *scr; 

    screen = DefaultScreen(d); 
    scr = DefaultScreenOfDisplay(d); 
    if (!*x || !*y) { 
     *x = WidthOfScreen(scr)/2; 
     *y = HeightOfScreen(scr)/2; 
     da = 
      XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, *x, *y, 0, 0, 0); 
    } else 
     da = 
      XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, *x, *y, 0, 0, 0); 

    XSelectInput(d, da, ButtonPressMask | ButtonReleaseMask | KeyPressMask | 
          ButtonMotionMask | StructureNotifyMask); 

    // http://www.lemoda.net/c/xlib-wmclose/index.html 
    /* "wm_delete_window" is the Atom which corresponds to the delete 
      window message sent by the window manager. */ 
    Atom wm_delete_window; 
    wm_delete_window = XInternAtom(d, "WM_DELETE_WINDOW", False); 
    /* Set up the window manager protocols. The third argument here is 
     meant to be an array, and the fourth argument is the size of 
     the array. */ 

    XSetWMProtocols(d, da, &wm_delete_window, 1); 
    XMapWindow(d, da); 

    sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), *x, *y); 

    return sfc; 
} 

struct Drawer { 
    Drawer() { 
     d = XOpenDisplay(NULL); 
     if (d == NULL) { 
      fprintf(stderr, "Failed to open display\n"); 
      exit(-1); 
     } 
     // create a new cairo surface in an x11 window as well as a cairo_t* to 
     // draw on the x11 window with. 
     int x=500, y=500; 
     surface = create_x11_surface(d, &x, &y); 
     cr = cairo_create(surface); 
    } 

    // https://stackoverflow.com/a/19308254/2725810 
    ~Drawer() { 
     cairo_destroy(cr); 
     cairo_surface_destroy(surface); 
     XCloseDisplay(d); 
    } 

    // Returns true if need to continue or false if quiting 
    bool processEvents() { 
     XEvent e; 

     if (XPending(cairo_xlib_surface_get_display(surface))) { 
      XNextEvent(cairo_xlib_surface_get_display(surface), &e); 
      switch (e.type) { 
      case ButtonPress: 
       drag_start_x = e.xbutton.x; 
       drag_start_y = e.xbutton.y; 
       break; 
      case ButtonRelease: 
       last_delta_x = 0; 
       last_delta_y = 0; 
       break; 
      case MotionNotify: 
       // http://cairographics.org/manual/cairo-Transformations.html#cairo-translate 
       cairo_translate(cr, e.xmotion.x - drag_start_x - last_delta_x, 
           e.xmotion.y - drag_start_y - last_delta_y); 
       last_delta_x = e.xmotion.x - drag_start_x; 
       last_delta_y = e.xmotion.y - drag_start_y; 
       break; 
      case ConfigureNotify: 
       cairo_xlib_surface_set_size(surface, e.xconfigure.width, 
              e.xconfigure.height); 
       break; 
      case ClientMessage: 
       return false; 
      default: 
       fprintf(stderr, "Dropping unhandled XEevent.type = %d.\n", 
         e.type); 
      } 
     } 
     return true; 
    } 

    void draw() { 
     cairo_push_group(cr); 

     // Clear the background 
     cairo_set_source_rgb(cr, 0, 0, 0); 
     cairo_paint(cr); 

     cairo_set_source_rgb(cr, 0, 1, 0); 
     cairo_move_to(cr, 0, 0); 
     cairo_line_to(cr, 256, 256); 
     cairo_move_to(cr, 256, 0); 
     cairo_line_to(cr, 0, 256); 
     cairo_set_line_width(cr, 10.0); 
     cairo_stroke(cr); 

     cairo_pop_group_to_source(cr); 
     cairo_paint(cr); 
     cairo_surface_flush(surface); 
     XFlush(d); 
    } 

    void run() { 
     while (1) { 
      if (!processEvents()) break; 
      draw(); 
      sleep(0.1); 
     } 
    } 

private: 
    Display *d; 
    cairo_surface_t* surface; 
    cairo_t* cr; 
    int last_delta_x = 0, last_delta_y = 0; 
    int drag_start_x, drag_start_y; 
}; 

int main() { 
    Drawer d; 
    d.run(); 
    return 0; 
} 

Répondre

0

TL; DR: Je ne vois pas toute fuite.

Voici ma version de la sortie valgrind (avec une version de débogage de caire et Pixman (qui signifie « avec des symboles ») (Oh et moi avons aussi ajouté un appel à cairo_debug_reset_static_data()):

==4035== HEAP SUMMARY: 
==4035==  in use at exit: 86,640 bytes in 9 blocks 
==4035== total heap usage: 6,736 allocs, 6,727 frees, 6,728,014 bytes allocated 
==4035== 
==4035== 128 bytes in 1 blocks are still reachable in loss record 1 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x4EA6044: cairo_pattern_create_for_surface (cairo-pattern.c:739) 
==4035== by 0x4E6507F: _cairo_default_context_pop_group (cairo-default-context.c:238) 
==4035== by 0x4E59E10: cairo_pop_group (cairo.c:554) 
==4035== by 0x4E59E10: cairo_pop_group_to_source (cairo.c:594) 
==4035== by 0x4017E0: Drawer::draw() (test.cpp:120) 
==4035== by 0x40183E: Drawer::run() (test.cpp:129) 
==4035== by 0x4013C6: main (test.cpp:144) 
==4035== 
==4035== 1,424 bytes in 1 blocks are still reachable in loss record 2 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x4E65D0B: _cairo_default_context_create (cairo-default-context.c:1463) 
==4035== by 0x4014B8: Drawer::Drawer() (test.cpp:59) 
==4035== by 0x4013BA: main (test.cpp:143) 
==4035== 
==4035== 2,064 bytes in 1 blocks are still reachable in loss record 3 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x636E8AA: _pixman_implementation_create (pixman-implementation.c:38) 
==4035== by 0x636D3EE: _pixman_implementation_create_general (pixman-general.c:250) 
==4035== by 0x636EF45: _pixman_choose_implementation (pixman-implementation.c:388) 
==4035== by 0x63262C8: pixman_constructor (pixman.c:39) 
==4035== by 0x400EA09: call_init.part.0 (dl-init.c:78) 
==4035== by 0x400EAF2: call_init (dl-init.c:36) 
==4035== by 0x400EAF2: _dl_init (dl-init.c:126) 
==4035== by 0x40011C9: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==4035== 
==4035== 2,064 bytes in 1 blocks are still reachable in loss record 4 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x636E8AA: _pixman_implementation_create (pixman-implementation.c:38) 
==4035== by 0x636BF3F: _pixman_implementation_create_fast_path (pixman-fast-path.c:3286) 
==4035== by 0x636EF60: _pixman_choose_implementation (pixman-implementation.c:391) 
==4035== by 0x63262C8: pixman_constructor (pixman.c:39) 
==4035== by 0x400EA09: call_init.part.0 (dl-init.c:78) 
==4035== by 0x400EAF2: call_init (dl-init.c:36) 
==4035== by 0x400EAF2: _dl_init (dl-init.c:126) 
==4035== by 0x40011C9: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==4035== 
==4035== 2,064 bytes in 1 blocks are still reachable in loss record 5 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x636E8AA: _pixman_implementation_create (pixman-implementation.c:38) 
==4035== by 0x63871DF: _pixman_implementation_create_mmx (pixman-mmx.c:4021) 
==4035== by 0x63543C5: _pixman_x86_get_implementations (pixman-x86.c:234) 
==4035== by 0x636EF6B: _pixman_choose_implementation (pixman-implementation.c:393) 
==4035== by 0x63262C8: pixman_constructor (pixman.c:39) 
==4035== by 0x400EA09: call_init.part.0 (dl-init.c:78) 
==4035== by 0x400EAF2: call_init (dl-init.c:36) 
==4035== by 0x400EAF2: _dl_init (dl-init.c:126) 
==4035== by 0x40011C9: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==4035== 
==4035== 2,064 bytes in 1 blocks are still reachable in loss record 6 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x636E8AA: _pixman_implementation_create (pixman-implementation.c:38) 
==4035== by 0x63A82BF: _pixman_implementation_create_sse2 (pixman-sse2.c:6487) 
==4035== by 0x63543A5: _pixman_x86_get_implementations (pixman-x86.c:239) 
==4035== by 0x636EF6B: _pixman_choose_implementation (pixman-implementation.c:393) 
==4035== by 0x63262C8: pixman_constructor (pixman.c:39) 
==4035== by 0x400EA09: call_init.part.0 (dl-init.c:78) 
==4035== by 0x400EAF2: call_init (dl-init.c:36) 
==4035== by 0x400EAF2: _dl_init (dl-init.c:126) 
==4035== by 0x40011C9: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==4035== 
==4035== 2,064 bytes in 1 blocks are still reachable in loss record 7 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x636E8AA: _pixman_implementation_create (pixman-implementation.c:38) 
==4035== by 0x63A895F: _pixman_implementation_create_ssse3 (pixman-ssse3.c:345) 
==4035== by 0x636EF6B: _pixman_choose_implementation (pixman-implementation.c:393) 
==4035== by 0x63262C8: pixman_constructor (pixman.c:39) 
==4035== by 0x400EA09: call_init.part.0 (dl-init.c:78) 
==4035== by 0x400EAF2: call_init (dl-init.c:36) 
==4035== by 0x400EAF2: _dl_init (dl-init.c:126) 
==4035== by 0x40011C9: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==4035== 
==4035== 2,064 bytes in 1 blocks are still reachable in loss record 8 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x636E8AA: _pixman_implementation_create (pixman-implementation.c:38) 
==4035== by 0x63714CF: _pixman_implementation_create_noop (pixman-noop.c:155) 
==4035== by 0x63262C8: pixman_constructor (pixman.c:39) 
==4035== by 0x400EA09: call_init.part.0 (dl-init.c:78) 
==4035== by 0x400EAF2: call_init (dl-init.c:36) 
==4035== by 0x400EAF2: _dl_init (dl-init.c:126) 
==4035== by 0x40011C9: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==4035== 
==4035== 72,704 bytes in 1 blocks are still reachable in loss record 9 of 9 
==4035== at 0x4C28C4F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4035== by 0x554E11F: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21) 
==4035== by 0x400EA09: call_init.part.0 (dl-init.c:78) 
==4035== by 0x400EAF2: call_init (dl-init.c:36) 
==4035== by 0x400EAF2: _dl_init (dl-init.c:126) 
==4035== by 0x40011C9: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) 
==4035== 
==4035== LEAK SUMMARY: 
==4035== definitely lost: 0 bytes in 0 blocks 
==4035== indirectly lost: 0 bytes in 0 blocks 
==4035==  possibly lost: 0 bytes in 0 blocks 
==4035== still reachable: 86,640 bytes in 9 blocks 
==4035==   suppressed: 0 bytes in 0 blocks 
==4035== 
==4035== For counts of detected and suppressed errors, rerun with: -v 
==4035== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 

Non Idée sur les fuites dans libstdC++, mais puisque cela dans _dl_init, il devrait être inoffensif ("fuite" unique au démarrage)

La même chose vaut pour pixman_constructor: Pixman utilise des chemins de code optimisés en fonction de la CPU sur laquelle il Il s'agit d'une initialisation unique qui alloue de la mémoire qui ne peut pas être libérée.Il est inoffensif

Cela ne laisse que deux fuites. Le modèle affecté en interne à cairo_pop_group_to_source() n'est pas libéré, tout comme le contexte cairo créé par cairo_create(). Ces fuites se sont produites parce que j'ai mal placé l'appel à cairo_debug_reset_static_data(). Je l'appelais dans main qui est avant que le destructeur s'exécute. Le déplacer vers le destructeur fait disparaître cette fuite ... Désolé de ne pas le remarquer plus tôt et désolé d'être trop paresseux pour mettre à jour ce qui précède. Donc, pour moi, il y a une fuite attendue de pixman et une fuite inattendue de libstdC++. Aucun n'est lié au Caire. J'ai utilisé la version 1.14.2-95-g98d01cd de cairo pour ceci.

+0

Je sais que ces fuites (ou blocs atteignables) sont inoffensives. Leur seul mal est qu'ils polluent la sortie de 'valgrind' et je dois passer par toutes ces lignes inutiles pour arriver à ce dont je me soucie vraiment. Par conséquent, il est important pour moi d'avoir un moyen de supprimer toutes ces lignes inutiles. Aussi, aucune idée pourquoi je vois une fuite de 'cairo_stroke'? – AlwaysLearning

+0

Eh bien, quelle est votre version cairo? Peut-être que c'est quelque chose de spécifique à la version? En plus de ça, aucune idée. Je ne pense pas que ma version cairo fasse quelque chose de spécial. –

+0

Le paquet est appelé 'libcairo2-dev'. C'est celui fourni avec Ubuntu 14.04 LTS. Un moyen de savoir plus précisément? – AlwaysLearning