内存泄漏与Cairo [英] Memory leaks with Cairo

查看:366
本文介绍了内存泄漏与Cairo的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我第一次使用 Cairo 。我使用这个函数创建表面:

  //这个函数应该给我们一个新的x11表面。 
cairo_surface_t * create_x11_surface(Display * d,int * x,int * y){
Drawable da;
int screen;
cairo_surface_t * sfc;
屏幕* 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是与删除对应的Atom
窗口消息由窗口管理器发送。 * /
Atom wm_delete_window;
wm_delete_window = XInternAtom(d,WM_DELETE_WINDOW,False);
/ *设置窗口管理器协议。这里的第三个参数是
意味着一个数组,第四个参数是
数组的大小。 * /

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

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

return sfc;
}

My main()包括创建 Drawer 对象并调用其 run 方法。 Drawer 定义如下(稍微简化,未使用的模板参数未显示):

  struct Drawer {
Drawer(){
d = XOpenDisplay(NULL);
if(d == NULL){
fprintf(stderr,无法打开display\\\
);
exit(-1);
}
//在x11窗口中创建一个新的cairo表面,在x11窗口中创建一个cairo_t *到
//。
int x = 500,y = 500;
surface = create_x11_surface(d,& x,& y);
cr = cairo_create(surface);
}

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

//如果需要继续则返回true或如果退出则返回false
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;
默认值:
fprintf(stderr,Dropping unhandled XEevent.type =%d.\\\

e.type);
}
}
return true;
}

void draw(){
cairo_push_group(cr);

//清除背景
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:
显示* d;
cairo_surface_t * surface;
cairo_t * cr;
int last_delta_x = 0,last_delta_y = 0;
int drag_start_x,drag_start_y;
};

程序使用 gcc 版本4.8 .2。



valgrind 报告内存泄漏并指向调用 cairo_stroke 和其他 Cairo 函数作为泄漏原因。它还说,尽管事实上 Drawer 的析构函数被调用,程序完成时,一些内存仍然不会释放。下面是 valgrind 的输出:

  == 6897 == Memcheck ,存储器错误检测器
== 6897 ==版权所有(C)2002-2013和GNU GPL'd,由Julian Seward等人
== 6897 ==使用Valgrind-3.10.0.SVN和LibVEX;重新运行-h版权信息
== 6897 ==命令:./Test
== 6897 ==
删除未处理的XEevent.type = 21.
删除未处理的XEevent。 type = 19.
删除未处理的XEevent.type = 65.
== 6897 ==
== 6897 == HEAP SUMMARY:
== 6897 == in exit at exit :12,696字节在12块
== 6897 ==总堆使用:19,039分配,19,027释放,8,088,426字节分配
== 6897 ==
== 6897 == 1 2块在损失记录中仍然可达1 of 11
== 6897 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
== 6897 == by 0x4E59F7C:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5B5B9:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5BAE5:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5CAB0:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5D87D:? (在/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:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5FECF:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E57F01:cairo_push_group_with_content(在/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 == 1个块中的72个字节仍然可以在丢失记录2中找到11
== 6897 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 6897 == by 0x4E59F7C:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5B5B9:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5BAE5:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5CDB2:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4EB4DE3:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5DA63:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4ECEA3C:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4EA2411:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E651E1:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5F168:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E58994:cairo_stroke(在/usr/lib/x86_64-linux-gnu/libcairo.so中) .2.11301.0)
== 6897 ==
== 6897 == 1个块中的160个字节在丢失记录中仍然可达3 of 11
== 6897 == at 0x4C2AB80:malloc (在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 6897 == by 0x4E850BC:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E851BC:cairo_pattern_create_rgba(在/usr/lib/x86_64-linux-gnu/libcairo.so中) .2.11301.0)
== 6897 == by 0x4E6028A:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E57FC9:cairo_set_source_rgb(在/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 == 2个块中的256个字节在丢失记录中仍然可达4 of 11
== 6897 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
== 6897 == by 0x4E8529A:cairo_pattern_create_for_surface(在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5FD7F:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E57F48:cairo_pop_group(在/usr/lib/x86_64-linux-gnu/libcairo.so中) .2.11301.0)
== 6897 == by 0x4E5809D:cairo_pop_group_to_source(在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x405A38 :抽屉< 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 == 1个块中的352字节绝对丢失在丢失记录5中11
== 6897 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
== 6897 == by 0x4ECC831:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4ECC933:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4ECD497:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4EB3922:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4EB4E32:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5DA63:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4ECEA3C:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4EA2411:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E651E1:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E5F168:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 6897 == by 0x4E58994:cairo_stroke(在/usr/lib/x86_64-linux-gnu/libcairo.so中) .2.11301.0)
== 6897 ==
== 6897 == 1块中的1,424字节在丢失记录中仍然可达6 of 11
== 6897 == at 0x4C2AB80:malloc (在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 6897 == by 0x4E604E7:? (在/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字节在1块中仍然可以在丢失记录中获得7 of 11
== 6897 == at 0x4C2AB80:malloc(在/ usr / lib / valgrind / vgpreload_memcheck-amd64-linux.so)
== 6897 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5FCBACE:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5FCD585:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so中)
== 6897 ==
== 6897 == 1个块中的2,072字节在丢失记录中仍然可达8 of 11
== 6897 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
== 6897 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5FCA61F:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5FCD5A0:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 6897 ==
== 6897 == 1个块中的2,072字节在丢失记录中仍然可达9 of 11
== 6897 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
== 6897 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5FE5A8F:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5FBC1A5:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5FCD5AB:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 6897 ==
== 6897 == 1块中的2,072字节在丢失记录中仍然可达10 of 11
== 6897 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
== 6897 == by 0x5FCCE9A:? (在/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:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 6897 ==
== 6897 == 1个块中的2,072字节在丢失记录中仍然可达11 of 11
== 6897 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
== 6897 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5FCFCBF:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 6897 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 6897 ==
== 6897 ==漏洞摘要:
== 6897 == definitely lost: 352字节在1块
== 6897 ==间接丢失:0字节在0块
== 6897 ==可能丢失:0字节在0块
== 6897 ==仍然可达:11块中的12,344字节
== 6897 == suppress:0块在0块
== 6897 ==
== 6897 ==对于检测到的和抑制的错误计数,重新运行:-v
== 6897 == ERROR摘要:1个上下文中的1个错误(抑制:0从0)


:插入对 cairo_debug_reset_static_data()的调用后, )从建议的此处的析构函数中,输出 valgrind 变得有点短:

  == 7310 == Memcheck,内存错误检测器
= = 7310 == Copyright(C)2002-2013,and GNU GPL'd,by Julian Seward et al。
== 7310 ==使用Valgrind-3.10.0.SVN和LibVEX;重新运行-h版权信息
== 7310 ==命令:./Test
== 7310 ==
删除未处理的XEevent.type = 21.
删除未处理的XEevent。 type = 19.
删除未处理的XEevent.type = 65.
== 7310 ==
== 7310 == HEAP SUMMARY:
== 7310 == in exit at exit :10,712字节在6块
== 7310 ==总堆使用:29,352分配,29,346释放,12,459,938字节分配
== 7310 ==
== 7310 == 1 352字节块肯定丢失在丢失记录1 6
== 7310 ==在0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 7310 ==通过0x4ECC831:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 7310 == by 0x4ECC933:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 7310 == by 0x4ECD497:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 7310 == by 0x4EB3922:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 7310 == by 0x4EB4E32:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 7310 == by 0x4E5DA63:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 7310 == by 0x4ECEA3C:? (在/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:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 7310 == by 0x4E5F168:? (在/usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0)
== 7310 == by 0x4E58994:cairo_stroke(在/usr/lib/x86_64-linux-gnu/libcairo.so .2.11301.0)
== 7310 ==
== 7310 == 1个块中的2,072个字节仍然可以在丢失记录2中找到6
== 7310 == at 0x4C2AB80:malloc (在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 7310 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FCBACE:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FCD585:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 7310 ==
== 7310 == 1块中的2,072字节仍然可以在损失记录3中找到6
== 7310 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 7310 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FCA61F:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FCD5A0:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 7310 ==
== 7310 == 1块中的2,072字节仍然可以在损失记录4中找到6
== 7310 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 7310 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FE5A8F:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FBC1A5:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FCD5AB:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so中)
== 7310 ==
== 7310 == 1个块中的2,072字节在丢失记录中仍然可达6 of 6
== 7310 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 7310 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x60053CF:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FCD5AB:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 7310 ==
== 7310 == 1块中的2,072字节仍然可以在损失记录6中找到6
== 7310 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
== 7310 == by 0x5FCCE9A:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5FCFCBF:? (在/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
== 7310 == by 0x5F7F508:? (在/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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 7310 ==
== 7310 == LEAK摘要:
== 7310 == definitely lost: 352字节在1块
== 7310 ==间接丢失:0字节在0块
== 7310 ==可能丢失:0字节在0块
== 7310 ==仍然可达:5块中的10,360字节
== 7310 ==被抑制:0块中的0字节
== 7310 ==
== 7310 ==对于检测和抑制错误的计数,重新运行:-v
== 7310 == ERROR摘要:1个上下文中的1个错误(抑制:0从0)


b $ b

BTW,为什么 valgrind 显示丢失记录的完整调用堆栈,并停止在 cairo_stroke 改为?我的程序用 gcc -g 标志...

编译

UPDATE :根据评论中的要求,这里是整个工作示例:

  #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>

//这个函数应该给我们一个新的x11表面。
cairo_surface_t * create_x11_surface(Display * d,int * x,int * y){
Drawable da;
int screen;
cairo_surface_t * sfc;
屏幕* 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是与删除对应的Atom
窗口消息由窗口管理器发送。 * /
Atom wm_delete_window;
wm_delete_window = XInternAtom(d,WM_DELETE_WINDOW,False);
/ *设置窗口管理器协议。这里的第三个参数是
意味着一个数组,第四个参数是
数组的大小。 * /

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,无法打开display\\\
);
exit(-1);
}
//在x11窗口中创建一个新的cairo表面,在x11窗口中创建一个cairo_t *到
//。
int x = 500,y = 500;
surface = create_x11_surface(d,& x,& y);
cr = cairo_create(surface);
}

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

//如果需要继续则返回true或如果退出则返回false
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;
默认值:
fprintf(stderr,Dropping unhandled XEevent.type =%d.\\\

e.type);
}
}
return true;
}

void draw(){
cairo_push_group(cr);

//清除背景
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:
显示* 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;
}


解决方案

TL; DR:I don没有看到任何泄漏。



这是我的valgrind输出版本(使用cairo和pixman的调试版本我还添加了对 cairo_debug_reset_static_data()的调用:

  == 4035 == HEAP摘要:
== 4035 ==在退出时使用:在9块中为86,640字节
== 4035 ==总堆使用:6,736分配,6,727释放,6,728,014字节分配
== 4035 ==
== 4035 == 1个块中的128个字节仍然可以在丢失记录1中找到1
== 4035 == at 0x4C28C4F:malloc(在/ 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个块中的1,424字节仍然可以在丢失记录中找到2 $ 9
== 4035 == at 0x4C28C4F:malloc(在/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 == 1个块中的2,064字节在丢失记录中仍然可达3 of 9
== 4035 == at 0x4C28C4F:malloc(在/ 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:? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 4035 ==
== 4035 == 1块中的2,064字节在丢失记录中仍然可达4 of 9
== 4035 == at 0x4C28C4F:malloc(在/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:? ?? (在/lib/x86_64-linux-gnu/ld-2.19.so)
== 4035 ==
== 4035 == 1块中的2,064字节仍然可以在丢失记录中找到5 of 9
== 4035 == at 0x4C28C4F:malloc(在/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)

No idea about the leaks in libstdc++, but since this in _dl_init, it should be harmless (one-time \"leak\" during startup).



The same holds for pixman_constructor: Pixman uses optimized code paths based on the CPU on which it runs. This is a one-time initialization that allocates memory that cannot be freed. It’s harmless.



That leaves only two leaks. The pattern that is internally allocated in cairo_pop_group_to_source() isn’t freed, but so is the cairo context created by cairo_create(). These leaks occurred because I mis-placed the call to cairo_debug_reset_static_data(). I was calling this in main which is before the destructor runs. Moving it to the destructor makes this leak disappear... Sorry for not noticing this earlier and sorry for being too lazy to update the above.



So for me there is an expected leak from pixman and an unexpected leak from libstdc++. Neither is related to cairo. I used cairo version 1.14.2-95-g98d01cd for this.


This is my first experience with Cairo. I create the surface using this function:

//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;
}

My main() consists of creating a Drawer object and calling its run method. Drawer is defined as follows (slightly simplified, the unused template parameter is not shown):

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);
    }

    // http://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;
};

The program is compiled with gcc version 4.8.2.

valgrind reports memory leaks and points to calls to cairo_stroke and other Cairo functions as the leak causes. It also says that some memory remains not freed when the program finishes despite the fact that Drawer's destructor gets called. Here is the output of 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)

What am I not doing right?

UPDATE: After inserting a call to cairo_debug_reset_static_data() from the destructor as suggested here, the output of valgrind became somewhat shorter:

==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, why doesn't valgrind show the full callstack for the lost record and stops at cairo_stroke instead? My program is compiled with gcc with the -g flag...

UPDATE: As requested in the comments, here is the whole working example:

#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);
    }

    // http://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;
}

解决方案

TL;DR: I don't see any leak.

Here is my version of the valgrind output (with a debug version of cairo and pixman (which means "with symbols"); (Oh and I also added a call to 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)

No idea about the leaks in libstdc++, but since this in _dl_init, it should be harmless (one-time "leak" during startup).

The same holds for pixman_constructor: Pixman uses optimized code paths based on the CPU on which it runs. This is a one-time initialization that allocates memory that cannot be freed. It's harmless.

That leaves only two leaks. The pattern that is internally allocated in cairo_pop_group_to_source() isn't freed, but so is the cairo context created by cairo_create(). These leaks occurred because I mis-placed the call to cairo_debug_reset_static_data(). I was calling this in main which is before the destructor runs. Moving it to the destructor makes this leak disappear... Sorry for not noticing this earlier and sorry for being too lazy to update the above.

So for me there is an expected leak from pixman and an unexpected leak from libstdc++. Neither is related to cairo. I used cairo version 1.14.2-95-g98d01cd for this.

这篇关于内存泄漏与Cairo的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆