2009-07-03

valgrind against glib

上午同事说valgrind在扫描基于glib的程序时有些明显的内存泄漏没有报过出来。有点不相信,因为之前每次怀疑valgrind的时候最终总是证明是自己的代码写的不对。于是,将信将疑之下用valgrind扫了一下下面的程序:
GList* list = NULL;
GList* i = NULL;

list = g_list_append(list, g_strdup("first"));
list = g_list_append(list, g_strdup("second"));

for(i = list; i != NULL; i = g_list_next(i)){
printf("%s\n", (char *)i->data);
}

令人难以置信的是,其结果居然是:
==6509== LEAK SUMMARY:
==6509== definitely lost: 0 bytes in 0 blocks.
==6509== possibly lost: 0 bytes in 0 blocks.
==6509== still reachable: 4,569 bytes in 10 blocks.
==6509== suppressed: 0 bytes in 0 blocks.


两次g_strdup()出来的内存显然没有释放,而且链表本身占有的内存也没有释放,但valgrind的definitely/possibly lost居然都是0!如果把上面的printf()函数换成glib里面的g_print()函数,结果又有所变化:
==6519== LEAK SUMMARY:
==6519== definitely lost: 0 bytes in 0 blocks.
==6519== possibly lost: 744 bytes in 3 blocks.
==6519== still reachable: 5,407 bytes in 18 blocks.
==6519== suppressed: 0 bytes in 0 blocks.


这次不但多了744字节的possibly lost,还多出了838字节的still reachable。Google了一把,发现这个问题似乎和glib的slice allocator有关系。参考这里。如果想让valgrind展现出正确的行为,请将环境变量G_SLICE设为always-malloc。


# G_SLICE=always-malloc valgrind --leak-check=yes ./foo
...
==6522== LEAK SUMMARY:
==6522== definitely lost: 12 bytes in 1 blocks.
==6522== indirectly lost: 25 bytes in 3 blocks.
==6522== possibly lost: 0 bytes in 0 blocks.
==6522== still reachable: 1,638 bytes in 9 blocks.
==6522== suppressed: 0 bytes in 0 blocks.

标签: ,

0 Comments:

发表评论

<< Home