简体   繁体   中英

Valgrind gives possibly lost memory with g_test_trap_subprocess ()

I am currently working on unit tests with glib-Testing for a C library I am writing. Part of these tests check that code fails on expected occasions (I am used to these sort of tests from Python where you would assert a certain Exception was raised). I am using the recipe in the manual for glib-Testing for g_test_trap_subprocess () (see minimal example below) which works fine from the unit-testing point of view and gives the correct tests.

My problem is when I run valgrind on the following minimal example ( test_glib.c ):

#include <glib.h>

void test_possibly_lost(){
        if (g_test_subprocess()){
                g_assert(1 > 2);
        }
        g_test_trap_subprocess(NULL, 0, 0);
        g_test_trap_assert_failed();
}

int main(int argc, char **argv){
        g_test_init(&argc, &argv, NULL);

        g_test_add_func("/set1/test", test_possibly_lost);

        return g_test_run();
}

compiled with

gcc `pkg-config --libs --cflags glib-2.0` test_glib.c

The output of valgrind --leak-check=full ./a.out is then

==15260== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==15260== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==15260== Command: ./a.out
==15260== 
/set1/test: OK
==15260== 
==15260== HEAP SUMMARY:
==15260==     in use at exit: 24,711 bytes in 40 blocks
==15260==   total heap usage: 2,507 allocs, 2,467 frees, 235,121 bytes allocated
==15260== 
==15260== 272 bytes in 1 blocks are possibly lost in loss record 36 of 40
==15260==    at 0x483AB65: calloc (vg_replace_malloc.c:752)
==15260==    by 0x4012AC1: allocate_dtv (in /usr/lib/ld-2.29.so)
==15260==    by 0x4013431: _dl_allocate_tls (in /usr/lib/ld-2.29.so)
==15260==    by 0x4BD51AD: pthread_create@@GLIBC_2.2.5 (in /usr/lib/libpthread-2.29.so)
==15260==    by 0x48BE42A: ??? (in /usr/lib/libglib-2.0.so.0.6000.6)
==15260==    by 0x48BE658: g_thread_new (in /usr/lib/libglib-2.0.so.0.6000.6)
==15260==    by 0x48DCBF0: ??? (in /usr/lib/libglib-2.0.so.0.6000.6)
==15260==    by 0x48DCC43: ??? (in /usr/lib/libglib-2.0.so.0.6000.6)
==15260==    by 0x48DCD11: g_child_watch_source_new (in /usr/lib/libglib-2.0.so.0.6000.6)
==15260==    by 0x48B7DF4: ??? (in /usr/lib/libglib-2.0.so.0.6000.6)
==15260==    by 0x48BEA93: g_test_trap_subprocess (in /usr/lib/libglib-2.0.so.0.6000.6)
==15260==    by 0x1091DD: test_possibly_lost (in /dir/to/aout/a.out)
==15260== 
==15260== LEAK SUMMARY:
==15260==    definitely lost: 0 bytes in 0 blocks
==15260==    indirectly lost: 0 bytes in 0 blocks
==15260==      possibly lost: 272 bytes in 1 blocks
==15260==    still reachable: 24,439 bytes in 39 blocks
==15260==         suppressed: 0 bytes in 0 blocks
==15260== Reachable blocks (those to which a pointer was found) are not shown.
==15260== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==15260== 
==15260== For counts of detected and suppressed errors, rerun with: -v
==15260== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

The possibly lost memory bothers me, coincidentally my code also possibly loses 272 bytes so I think this might be a problem with the way I use glib rather than my own structs. Personally, I would treat possibly lost memory as definitely lost and I would like to get rid of it.

So my question is whether there is a free that I could cleverly insert to free the memory, a different recipe to check for failed asserts or are these lost 272 bytes just something I will have to live with?

That's a somewhat odd stack trace for the allocation. g_test_trap_subprocess() is supposed to run the specified test(s) in a subprocess, but it is creating a thread. These are not mutually exclusive -- a subprocess may well also be forked -- but mixing threads with forking is a tricky, finicky business.

In any event, the trace seems to indicate that the problem arises from glib starting a thread that is not properly terminated and cleaned up before your program exits. Since the issue is with an internal thread, the best solution would involve calling an appropriate shutdown function. I don't see such a function documented either specifically for g_test or more generally among the GLib utility functions, nor do I see any documentation of a need to call such a function, so I'm going to attribute the issue to a minor flaw in Glib.

Unless you can find a glib-based solution that I missed, your best alternative is probably to accept that what you're seeing is a glib quirk, and to write a Valgrind suppression file that you can then use to instruct Valgrind not to report on it . Note that although you can write such a file by hand, using the information provided in the leak report, the easiest way to get one is to run Valgrind with the --gen-suppressions=yes option. However you get it, you can instruct valgrind to use it on subsequent runs by using a --suppressions=/path/to/file.supp option on the Valgrind command line.

Do consult the Valgrind manual (linked above) for details on suppression files, including format, how to create and modify them, and how to use them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM