glib: valgrind сообщает о "все еще достижимых" блоках после g_strsplit
У меня есть очень простой кусок кода:
#include <stdio.h>
#include <glib.h>
int main(int argc, char * argv[])
{
const char * path = "/a/b/c/d/e/f/g/h/";
gchar ** parts = NULL;
int i;
parts = g_strsplit( (const gchar *) path, "/", 0 );
for ( i = 0; parts[i]; i++ ) {
if (parts[i][0] == '\0') {
continue;
}
printf("part: %s\n", parts[i]);
}
g_strfreev( parts );
return 0;
}
Однако, когда я запускаю этот код через Valgrind, я получаю кучу "все еще доступных" блоков:
==12924==
==12924== HEAP SUMMARY:
==12924== in use at exit: 4,252 bytes in 8 blocks
==12924== total heap usage: 19 allocs, 11 frees, 4,358 bytes allocated
==12924==
==12924== 240 bytes in 1 blocks are still reachable in loss record 1 of 6
==12924== at 0x4A04820: memalign (vg_replace_malloc.c:581)
==12924== by 0x4A048D7: posix_memalign (vg_replace_malloc.c:709)
==12924== by 0x36A8255F87: ??? (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825680B: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8257DBD: g_slist_prepend (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825AB15: g_strsplit (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x4005C8: main (strsplit.c:10)
==12924==
==12924== 252 bytes in 1 blocks are still reachable in loss record 2 of 6
==12924== at 0x4A04A28: calloc (vg_replace_malloc.c:467)
==12924== by 0x36A8241707: g_malloc0 (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8255742: ??? (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825669D: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8257DBD: g_slist_prepend (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825AB15: g_strsplit (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x4005C8: main (strsplit.c:10)
==12924==
==12924== 504 bytes in 1 blocks are still reachable in loss record 3 of 6
==12924== at 0x4A04A28: calloc (vg_replace_malloc.c:467)
==12924== by 0x36A8241707: g_malloc0 (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8255722: ??? (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825669D: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8257DBD: g_slist_prepend (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825AB15: g_strsplit (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x4005C8: main (strsplit.c:10)
==12924==
==12924== 504 bytes in 1 blocks are still reachable in loss record 4 of 6
==12924== at 0x4A04A28: calloc (vg_replace_malloc.c:467)
==12924== by 0x36A8241707: g_malloc0 (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825578B: ??? (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825669D: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8257DBD: g_slist_prepend (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825AB15: g_strsplit (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x4005C8: main (strsplit.c:10)
==12924==
==12924== 720 bytes in 3 blocks are still reachable in loss record 5 of 6
==12924== at 0x4A04820: memalign (vg_replace_malloc.c:581)
==12924== by 0x4A048D7: posix_memalign (vg_replace_malloc.c:709)
==12924== by 0x36A8255F87: ??? (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8256841: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8257DBD: g_slist_prepend (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825AB15: g_strsplit (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x4005C8: main (strsplit.c:10)
==12924==
==12924== 2,032 bytes in 1 blocks are still reachable in loss record 6 of 6
==12924== at 0x4A04A28: calloc (vg_replace_malloc.c:467)
==12924== by 0x36A8241707: g_malloc0 (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8256642: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A8257DBD: g_slist_prepend (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x36A825AB15: g_strsplit (in /lib64/libglib-2.0.so.0.2200.5)
==12924== by 0x4005C8: main (strsplit.c:10)
==12924==
==12924== LEAK SUMMARY:
==12924== definitely lost: 0 bytes in 0 blocks
==12924== indirectly lost: 0 bytes in 0 blocks
==12924== possibly lost: 0 bytes in 0 blocks
==12924== still reachable: 4,252 bytes in 8 blocks
==12924== suppressed: 0 bytes in 0 blocks
==12924==
==12924== For counts of detected and suppressed errors, rerun with: -v
==12924== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
У меня вопрос: не убрал ли я должным образом или эти ошибки можно безопасно игнорировать?
Спасибо!
3 ответа
Поскольку существуют различные типы утечек разной степени серьезности, возникает интересный вопрос: какие утечки следует считать истинными "ошибками", а какие - нет?
Определенно потерянные и, возможно, потерянные блоки считаются истинными "ошибками". Косвенно потерянные и все еще достижимые блоки не считаются истинными "ошибками", даже если указано --show-достижимое = да, и они печатаются; это потому, что такие блоки не нуждаются в прямом исправлении программистом.
Таким образом, вы можете спокойно игнорировать эти ошибки, так как эти блоки будут в любом случае повторно заявлены при выходе из программы.
Также прочитайте эту ветку SO, в которой подробно обсуждались ошибки памяти Valgrind.
Этот документ может помочь понять, какой тип утечек обнаруживает Valgrind / memcheck.
Что касается самой проблемы, сначала не запускайте valgrind в программе на основе GLib, используя slice-allocator по умолчанию в GLib, так как это даст вам много "мусора" в журнале valgrind. Просто запустите программу, указывающую GLib использовать простые malloc:
$ G_DEBUG=always-malloc valgrind --leak-check=full --show-reachable=yes your-program your-args
Program received signal SIGSEGV, Segmentation fault.
in g_slice_alloc () from /usr/local/lib/libglib-2.0.so.0
(gdb) backtrace
in g_slice_alloc () from /usr/local/lib/libglib-2.0.so.0
in g_slist_prepend () from /usr/local/lib/libglib-2.0.so.0
in g_strsplit () from /usr/local/lib/libglib-2.0.so.0
Угадайте, что-то не так с распределением в glib. Многие другие проекты, которые используют Glib, также имеют такие проблемы.