简体   繁体   English

Valgrind使用g_test_trap_subprocess()可能会丢失内存

[英]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. 我目前正在使用glib-Testing对我正在编写的C库进行单元测试。 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). 这些测试的一部分检查代码是否在预期的情况下失败(我习惯了来自Python的此类测试,在这些测试中您会断言某些异常)。 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. 我正在使用g_test_trap_subprocess () glib-Testing手册中的配方(请参见下面的最小示例),从单元测试的角度来看,它可以正常工作并给出正确的测试。

My problem is when I run valgrind on the following minimal example ( test_glib.c ): 我的问题是在以下最小示例( test_glib.c )上运行valgrind时:

#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 然后valgrind --leak-check=full ./a.out的输出是

==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. 可能丢失的内存使我感到困扰,巧合的是,我的代码也可能丢失了272个字节,因此我认为这可能是我使用glib而不是我自己的结构的方式的问题。 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? 所以我的问题是,是否有一个free ,我可以巧妙地插入释放内存,不同的配方来检查失败断言或在这些丢失的272个字节只是我将不得不住在一起?

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. g_test_trap_subprocess()应该在子进程中运行指定的测试,但是它正在创建线程。 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. 无论如何,跟踪似乎表明问题是由于glib启动了一个线程而导致的,该线程在程序退出之前未正确终止并清除。 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. 我没有看到专门针对g_test或更广泛地记录在GLib实用程序函数中的此类函数,也没有看到需要调用此类函数的任何文档,因此我将问题归因于较小的缺陷在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 . 除非您找到我错过的基于glib的解决方案,否则最好的选择可能是接受您所看到的是glib怪癖,并编写Valgrind抑制文件 ,然后使用该文件 指示Valgrind不要报告它 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. 请注意,尽管您可以使用泄漏报告中提供的信息手动编写此类文件,但最简单的方法是使用--gen-suppressions=yes选项运行Valgrind。 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. 无论您如何获得它,都可以通过在Valgrind命令行上使用--suppressions=/path/to/file.supp选项来指示valgrind在后续运行中使用它。

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. 请查阅Valgrind手册(上文链接)以获取抑制文件的详细信息,包括格式,如何创建和修改它们以及如何使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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