我正在尝试使用一些基本的 C 代码检索 linux 组,但是 getgrnam 和 getgrnam_r 都遇到内存泄漏。仅当
/etc/group
中缺少 linux 组时才会发生内存泄漏。
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <grp.h>
#include <pwd.h>
static char* group_name = "dummy";
static void test_getgrnam_r(void) {
struct group grp;
struct group* group = NULL;
int bufsize = 0;
int retval = -1;
char* buf = NULL;
bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
if(bufsize == -1) {
bufsize = 16384;
}
buf = calloc(1, bufsize);
retval = getgrnam_r(group_name, &grp, buf, bufsize, &group);
printf("retval = %d\n", retval);
free(buf);
free(group);
}
static void test_getgrnam(void) {
struct group* group = getgrnam(group_name);
}
int main(void) {
test_getgrnam();
//test_getgrnam_r();
}
可以使用简单的 gcc 命令来编译此代码:
gcc main.c -o out
并且可以使用 valgrind 运行它来显示内存泄漏:
valgrind --leak-check=full --show-leak-kinds=all ./out
==2255356== Memcheck, a memory error detector
==2255356== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2255356== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==2255356== Command: ./out
==2255356==
==2255356==
==2255356== HEAP SUMMARY:
==2255356== in use at exit: 5,177 bytes in 13 blocks
==2255356== total heap usage: 77 allocs, 64 frees, 19,669 bytes allocated
==2255356==
==2255356== 46 bytes in 1 blocks are still reachable in loss record 1 of 8
==2255356== at 0x483877F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255356== by 0x401C26A: strdup (strdup.c:42)
==2255356== by 0x40172FB: _dl_load_cache_lookup (dl-cache.c:338)
==2255356== by 0x4009776: _dl_map_object (dl-load.c:2102)
==2255356== by 0x4013D41: dl_open_worker (dl-open.c:513)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x40138F9: _dl_open (dl-open.c:837)
==2255356== by 0x4986FCC: do_dlopen (dl-libc.c:96)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x4987C0E: _dl_catch_error (dl-error-skeleton.c:227)
==2255356== by 0x49870A6: dlerror_run (dl-libc.c:46)
==2255356== by 0x4987135: __libc_dlopen_mode (dl-libc.c:195)
==2255356==
==2255356== 46 bytes in 1 blocks are still reachable in loss record 2 of 8
==2255356== at 0x483877F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255356== by 0x400BFB7: _dl_new_object (dl-object.c:196)
==2255356== by 0x4007255: _dl_map_object_from_fd (dl-load.c:997)
==2255356== by 0x4009274: _dl_map_object (dl-load.c:2236)
==2255356== by 0x4013D41: dl_open_worker (dl-open.c:513)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x40138F9: _dl_open (dl-open.c:837)
==2255356== by 0x4986FCC: do_dlopen (dl-libc.c:96)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x4987C0E: _dl_catch_error (dl-error-skeleton.c:227)
==2255356== by 0x49870A6: dlerror_run (dl-libc.c:46)
==2255356== by 0x4987135: __libc_dlopen_mode (dl-libc.c:195)
==2255356==
==2255356== 71 bytes in 2 blocks are still reachable in loss record 4 of 8
==2255356== at 0x483877F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255356== by 0x401C26A: strdup (strdup.c:42)
==2255356== by 0x40172FB: _dl_load_cache_lookup (dl-cache.c:338)
==2255356== by 0x4009776: _dl_map_object (dl-load.c:2102)
==2255356== by 0x400DDC0: openaux (dl-deps.c:64)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x400E138: _dl_map_object_deps (dl-deps.c:248)
==2255356== by 0x4013DAA: dl_open_worker (dl-open.c:571)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x40138F9: _dl_open (dl-open.c:837)
==2255356== by 0x4986FCC: do_dlopen (dl-libc.c:96)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356==
==2255356== 71 bytes in 2 blocks are still reachable in loss record 5 of 8
==2255356== at 0x483877F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255356== by 0x400BFB7: _dl_new_object (dl-object.c:196)
==2255356== by 0x4007255: _dl_map_object_from_fd (dl-load.c:997)
==2255356== by 0x4009274: _dl_map_object (dl-load.c:2236)
==2255356== by 0x400DDC0: openaux (dl-deps.c:64)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x400E138: _dl_map_object_deps (dl-deps.c:248)
==2255356== by 0x4013DAA: dl_open_worker (dl-open.c:571)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x40138F9: _dl_open (dl-open.c:837)
==2255356== by 0x4986FCC: do_dlopen (dl-libc.c:96)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356==
==2255356== 1,204 bytes in 1 blocks are still reachable in loss record 6 of 8
==2255356== at 0x483AB65: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255356== by 0x400BCDF: _dl_new_object (dl-object.c:89)
==2255356== by 0x4007255: _dl_map_object_from_fd (dl-load.c:997)
==2255356== by 0x4009274: _dl_map_object (dl-load.c:2236)
==2255356== by 0x4013D41: dl_open_worker (dl-open.c:513)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x40138F9: _dl_open (dl-open.c:837)
==2255356== by 0x4986FCC: do_dlopen (dl-libc.c:96)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x4987C0E: _dl_catch_error (dl-error-skeleton.c:227)
==2255356== by 0x49870A6: dlerror_run (dl-libc.c:46)
==2255356== by 0x4987135: __libc_dlopen_mode (dl-libc.c:195)
==2255356==
==2255356== 1,296 bytes in 3 blocks are still reachable in loss record 7 of 8
==2255356== at 0x483AB65: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255356== by 0x40116B6: _dl_check_map_versions (dl-version.c:274)
==2255356== by 0x4013DF5: dl_open_worker (dl-open.c:577)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x40138F9: _dl_open (dl-open.c:837)
==2255356== by 0x4986FCC: do_dlopen (dl-libc.c:96)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x4987C0E: _dl_catch_error (dl-error-skeleton.c:227)
==2255356== by 0x49870A6: dlerror_run (dl-libc.c:46)
==2255356== by 0x4987135: __libc_dlopen_mode (dl-libc.c:195)
==2255356== by 0x496F355: nss_load_library (nsswitch.c:359)
==2255356== by 0x496FBE8: __nss_lookup_function (nsswitch.c:467)
==2255356==
==2255356== 2,395 bytes in 2 blocks are still reachable in loss record 8 of 8
==2255356== at 0x483AB65: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255356== by 0x400BCDF: _dl_new_object (dl-object.c:89)
==2255356== by 0x4007255: _dl_map_object_from_fd (dl-load.c:997)
==2255356== by 0x4009274: _dl_map_object (dl-load.c:2236)
==2255356== by 0x400DDC0: openaux (dl-deps.c:64)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x400E138: _dl_map_object_deps (dl-deps.c:248)
==2255356== by 0x4013DAA: dl_open_worker (dl-open.c:571)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356== by 0x40138F9: _dl_open (dl-open.c:837)
==2255356== by 0x4986FCC: do_dlopen (dl-libc.c:96)
==2255356== by 0x4987B4F: _dl_catch_exception (dl-error-skeleton.c:208)
==2255356==
==2255356== LEAK SUMMARY:
==2255356== definitely lost: 0 bytes in 0 blocks
==2255356== indirectly lost: 0 bytes in 0 blocks
==2255356== possibly lost: 0 bytes in 0 blocks
==2255356== still reachable: 5,129 bytes in 12 blocks
==2255356== suppressed: 48 bytes in 1 blocks
==2255356==
==2255356== For lists of detected and suppressed errors, rerun with: -s
==2255356== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我发现了一些类似的帖子,但似乎都没有解决此问题的方法。
其中一些人建议使用
extern void __libc_freeres (void);
但是调用这个函数似乎也没有帮助。根据 valgrind 文档,我认为运行 valgrind 时已经默认调用此函数。
--run-libc-freeres=
[默认值:是]
https://valgrind.org/docs/manual/manual-core.html
这是否意味着我遇到了内存泄漏问题,或者是否有我尚未找到的解决方案?如果我可以提供额外信息,请告诉我。我试图让我的示例尽可能简单。
尝试将以下内容放入文件中
{
_dl_new_object
Memcheck:Leak
match-leak-kinds: reachable
...
fun:_dl_open
}
例如,dlopen.supp
然后运行
valgrind --leak-check=full --show-leak-kinds=all --suppressions=dlopen.supp
不同的 Linux 发行版之间存在一些差异,但上述抑制是广泛的,应该涵盖所有情况。