valgrind内存泄漏检测快速上手

举报
张俭 发表于 2023/12/30 08:57:36 2023/12/30
【摘要】 准备被测程序通过-g编译程序来携带debug信息,这样子输出的错误信息就可以包含精确的行号。如果你可以承受程序运行缓慢,那么我们可以使用-O0来编译程序。如果使用-O1,那么输出的行号可能会不准确。不推荐使用-O2及以上,因为 valgrind memcheck 偶尔会报告不存在的未初始化值错误。 运行程序如果平时这么运行myprog arg1 arg2就使用这个命令valgrind --...

准备被测程序

通过-g编译程序来携带debug信息,这样子输出的错误信息就可以包含精确的行号。如果你可以承受程序运行缓慢,那么我们可以使用-O0来编译程序。如果使用-O1,那么输出的行号可能会不准确。不推荐使用-O2及以上,因为 valgrind memcheck 偶尔会报告不存在的未初始化值错误。

运行程序

如果平时这么运行

myprog arg1 arg2

就使用这个命令

valgrind --leak-check=yes myprog arg1 arg2

Memcheck是默认的valgrind工具,--leak-check打开了内存泄漏检测开关。

通过这个命令运行,大约会比平时运行慢20到30倍,并且使用更大的内存。Memcheck 将发出它检测到的内存错误和泄漏的信息。

解释memcheck的输出

使用样例的C程序,包含一个内存分配错误和内存溢出

#include <stdlib.h>

void f(void)
{
   int* x = malloc(10 * sizeof(int));
   x[10] = 0;        // problem 1: heap block overrun
}                    // problem 2: memory leak -- x not freed

int main(void)
{
   f();
   return 0;
}

执行内存检测

gcc -g demo.c
valgrind ./a.out

输出信息如下

==145== Memcheck, a memory error detector
==145== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==145== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==145== Command: ./a.out
==145==
==145== Invalid write of size 4
==145==    at 0x401144: f (demo.c:6)
==145==    by 0x401155: main (demo.c:11)
==145==  Address 0x4a27068 is 0 bytes after a block of size 40 alloc'd
==145==    at 0x484086F: malloc (vg_replace_malloc.c:380)
==145==    by 0x401137: f (demo.c:5)
==145==    by 0x401155: main (demo.c:11)
==145==
==145==
==145== HEAP SUMMARY:
==145==     in use at exit: 40 bytes in 1 blocks
==145==   total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==145==
==145== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==145==    at 0x484086F: malloc (vg_replace_malloc.c:380)
==145==    by 0x401137: f (demo.c:5)
==145==    by 0x401155: main (demo.c:11)
==145==
==145== LEAK SUMMARY:
==145==    definitely lost: 40 bytes in 1 blocks
==145==    indirectly lost: 0 bytes in 0 blocks
==145==      possibly lost: 0 bytes in 0 blocks
==145==    still reachable: 0 bytes in 0 blocks
==145==         suppressed: 0 bytes in 0 blocks
==145==
==145== For lists of detected and suppressed errors, rerun with: -s
==145== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
  • 145 是进程号
  • 输出的第一行,即上方的第六行(Invalid write)表明了错误的类型。这里程序往不归它拥有的内存中写入了信息
  • 下方是错误的堆栈信息
  • 代码地址如0x401155通常并不重要,但有时候定位奇怪的问题可能会很关键
  • 一些错误信息会有第二段,用来描述所涉及的内存地址。上例指出写入的内存刚好超过 example.c 的第 5 行使用 malloc() 分配的块的末尾。

内存泄漏信息

==145== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==145==    at 0x484086F: malloc (vg_replace_malloc.c:380)
==145==    by 0x401137: f (demo.c:5)
==145==    by 0x401155: main (demo.c:11)

堆栈可以表明什么内存泄露了,但memcheck并不能告诉你内存泄漏的原因

valgrind会提示两种内存泄漏

  • “definitely lost”: 绝对泄漏了内存,必须修复
  • “probably lost”: 程序可能泄漏了内存,也有可能是一些特定的指针操作(如:指针放到了堆中)

参考

https://www.valgrind.org/docs/manual/quick-start.html#quick-start.intro

https://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.errormsgs

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。