Valgrind 使用 g_test_trap_subprocess () 给出可能丢失的内存
Valgrind gives possibly lost memory with g_test_trap_subprocess ()
我目前正在使用 glib-Testing 对我正在编写的 C 库进行单元测试。这些测试的一部分检查代码是否在预期的情况下失败(我习惯了来自 Python 的这类测试,你会断言某个异常被引发)。我正在使用 the manual for glib-Testing for g_test_trap_subprocess ()
中的方法(请参阅下面的最小示例),从单元测试的角度来看它工作正常并提供正确的测试。
我的问题是当我运行 valgrind 处理以下最小示例 (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();
}
编译为
gcc `pkg-config --libs --cflags glib-2.0` test_glib.c
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)
可能丢失的内存困扰着我,巧合的是我的代码也可能丢失 272 个字节,所以我认为这可能是我使用 glib 而不是我自己的结构的方式的问题。就个人而言,我会将可能丢失的记忆视为肯定丢失,我想摆脱它。
所以我的问题是是否有一个 free
我可以巧妙地插入以释放内存,一个不同的方法来检查失败的断言,或者这些丢失的 272 字节只是我必须忍受的东西?
分配的堆栈跟踪有点奇怪。 g_test_trap_subprocess()
应该 运行 子进程中的指定测试,但它正在创建一个线程。这些并不相互排斥——一个子进程也可能被分叉——但是将线程与分叉混合是一件棘手、挑剔的事情。
无论如何,跟踪似乎表明问题是由于 glib 启动了一个线程,该线程在程序退出之前未正确终止和清理。由于问题出在内部线程上,因此最好的解决方案是调用适当的关闭函数。我没有看到专门为 g_test 或更普遍地在 GLib 实用程序函数中记录这样的函数,也没有看到任何需要调用这样的函数的文档,所以我将归因于问题Glib 中的一个小缺陷。
除非你能找到我错过的基于 glib 的解决方案,否则你最好的选择可能是接受你所看到的是一个 glib 怪癖,并写下 a Valgrind suppression file that you can then use to instruct Valgrind not to report on it。请注意,尽管您可以使用泄漏报告中提供的信息手动编写这样的文件,但最简单的方法是使用 运行 带有 --gen-suppressions=yes
选项的 Valgrind。无论你得到它,你可以通过在 Valgrind 命令行上使用 --suppressions=/path/to/file.supp
选项来指示 valgrind 在随后的 运行s 上使用它。
请参阅 Valgrind 手册(上面链接)以了解有关抑制文件的详细信息,包括格式、如何创建和修改它们以及如何使用它们。
我目前正在使用 glib-Testing 对我正在编写的 C 库进行单元测试。这些测试的一部分检查代码是否在预期的情况下失败(我习惯了来自 Python 的这类测试,你会断言某个异常被引发)。我正在使用 the manual for glib-Testing for g_test_trap_subprocess ()
中的方法(请参阅下面的最小示例),从单元测试的角度来看它工作正常并提供正确的测试。
我的问题是当我运行 valgrind 处理以下最小示例 (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();
}
编译为
gcc `pkg-config --libs --cflags glib-2.0` test_glib.c
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)
可能丢失的内存困扰着我,巧合的是我的代码也可能丢失 272 个字节,所以我认为这可能是我使用 glib 而不是我自己的结构的方式的问题。就个人而言,我会将可能丢失的记忆视为肯定丢失,我想摆脱它。
所以我的问题是是否有一个 free
我可以巧妙地插入以释放内存,一个不同的方法来检查失败的断言,或者这些丢失的 272 字节只是我必须忍受的东西?
分配的堆栈跟踪有点奇怪。 g_test_trap_subprocess()
应该 运行 子进程中的指定测试,但它正在创建一个线程。这些并不相互排斥——一个子进程也可能被分叉——但是将线程与分叉混合是一件棘手、挑剔的事情。
无论如何,跟踪似乎表明问题是由于 glib 启动了一个线程,该线程在程序退出之前未正确终止和清理。由于问题出在内部线程上,因此最好的解决方案是调用适当的关闭函数。我没有看到专门为 g_test 或更普遍地在 GLib 实用程序函数中记录这样的函数,也没有看到任何需要调用这样的函数的文档,所以我将归因于问题Glib 中的一个小缺陷。
除非你能找到我错过的基于 glib 的解决方案,否则你最好的选择可能是接受你所看到的是一个 glib 怪癖,并写下 a Valgrind suppression file that you can then use to instruct Valgrind not to report on it。请注意,尽管您可以使用泄漏报告中提供的信息手动编写这样的文件,但最简单的方法是使用 运行 带有 --gen-suppressions=yes
选项的 Valgrind。无论你得到它,你可以通过在 Valgrind 命令行上使用 --suppressions=/path/to/file.supp
选项来指示 valgrind 在随后的 运行s 上使用它。
请参阅 Valgrind 手册(上面链接)以了解有关抑制文件的详细信息,包括格式、如何创建和修改它们以及如何使用它们。