我正在用 C 语言实现一个带有链表的优先级队列,但是当我打印出我的 pop
操作时出现内存泄漏。我还有另一个内存泄漏,我也试图找到它。
作为旁注,我通过 heapusage
而不是 d99kris
使用 Valgrind
。
这是我使用 printf
时的堆摘要:
HEAP SUMMARY:
in use at exit: 4112 bytes in 2 blocks
total heap usage: 10 allocs, 17 frees, 4536 bytes allocated
peak heap usage: 4256 bytes allocated
16 bytes in 1 block(s) are lost, originally allocated at:
LEAK SUMMARY:
definitely lost: 4112 bytes in 2 blocks
这是没有
printf
的堆摘要:HEAP SUMMARY:
in use at exit: 16 bytes in 1 blocks
total heap usage: 9 allocs, 10 frees, 440 bytes allocated
peak heap usage: 256 bytes allocated
LEAK SUMMARY:
definitely lost: 16 bytes in 1 blocks
我的
pop
函数:void *prio_q_pop(struct prio_q *q) {
q->size--;
struct elem *temp = q->first;
(q->first) = (q->first)->next;
void *asd = temp->datei;
free(temp);
return asd;
}
还有我的
main
函数,我在其中调用 printf
struct prio_q *queue;
char *s;
int i;
queue = prio_q_create();
push(queue, "Bye World", 0);
for (i = 0; i < 5; i++) {
s = prio_q_pop(queue);
//printf("%s\n", s);
}
s = prio_q_front(queue);
//printf("%s\n", s);
问题不是由我的代码引起的,而是内存检查器。以下程序泄漏 1 个块,堆使用量为 2 个分配和 4 个释放。
#include <stdio.h>
int main() {
printf("omer");
return 0;
}
最佳答案
这是一个误报。如果有的话,问题在于 heapusage 没有足够好的文档。我建议使用更好的泄漏检查器,例如泄漏 sanitizer 或 Valgrind。
我创建了一个文件 test.c
。
#include <stdio.h>
int main(int argc, char **argv) {
puts("Hello, world!");
}
使用泄漏 sanitizer ,没有错误。
$ cc -fsanitize=leak -g test.c
$ ./a.out
你好,世界!
使用地址 sanitizer ,没有错误。
$ cc -fsanitize=地址 -g test.c
$ ./a.out
你好,世界!
使用 Valgrind,没有错误。
$ cc -g test.c
$ valgrind ./a.out
==189174== Memcheck,内存错误检测器
==189174== 版权所有 (C) 2002-2017 和 GNU GPL,由 Julian Seward 等人所有。
==189174== 使用 Valgrind-3.13.0 和 LibVEX;使用 -h 重新运行以获取版权信息
==189174== 命令:./a.out
==189174==
你好,世界!
==189174==
==189174== 堆摘要:
==189174== 退出时正在使用:0 个块中的 0 个字节
==189174== 总堆使用量:1 次分配,1 次释放,已分配 1,024 字节
==189174==
==189174== 所有堆块都被释放——不可能有泄漏
==189174==
==189174== 对于检测到和抑制的错误的计数,重新运行: -v
==189174== 错误摘要:来自 0 个上下文的 0 个错误(被抑制:来自 0 的 0)
随着堆使用,泄漏!
$ cc -g test.c
$ ./heapusage ./a.out
你好,世界!
==189005== Heapusage - https://github.com/d99kris/heapusage
==189005==
==189005== 堆摘要:
==189005== 退出时使用:1 个块中的 1024 个字节
==189005== 总堆使用量:1 次分配,0 次释放,已分配 1024 字节
==189005== 峰值堆使用:已分配 1024 字节
==189005==
==189005== 1 个块中的 1024 个字节丢失,最初分配在:
==189005== 在 0x00007f99f0de56a7:malloc + 49
==189005== 在 0x00007f99f0a96a32:_IO_file_doallocate + 114
==189005== 在 0x00007f99f0aa4a46:_IO_doallocbuf + 70
==189005== 在 0x00007f99f0aa3da8:_IO_file_overflow + 472
==189005== 在 0x00007f99f0aa2e86:_IO_file_xsputn + 182
==189005== 在 0x00007f99f0a99033:_IO_puts + 211
==189005== 在 0x000055f667ee7655:
==189005== 在 0x00007f99f0a502b1:__libc_start_main + 241
==189005== 在 0x000055f667ee755a:
==189005==
==189005== 泄漏摘要:
==189005== 肯定丢失了:1 个块中的 1024 个字节
==189005==
分析
Heapusage 通过 Hook malloc 和 free 来工作(并且不扫描内存中的指针)。 Heapusage 没有在文档中完整解释这种方法的优点或缺点。一个优点是它很快,但缺点是它不精确。
特别是,我会指出 heapusage 给出了错误的消息:“绝对丢失”这个词在这里不适用!
如果您想要更好的错误消息,请使用上面推荐的工具之一:leak sanitizer 或 Valgrind (memcheck)。
总的来说,我还想提醒人们,使用这些工具,误报是生活中的事实。程序是否“Valgrind clean”与程序是否正确是不同的问题。
关于c - heapusage 检测到可能由 printf 引起的内存泄漏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55957454/