编译要求
编译时必须带 -g
-g 代表 Debug(调试)。它告诉编译器在编译汇编代码的同时,把源代码的额外信息(如变量名、函数名、数据类型和代码行号)以特定格式(如 DWARF 格式)写入到最终的可执行文件中。
常用编译格式:gcc -g -O0 -fno-omit-frame-pointer -Wall -Wextra -o app main.c foo.c
-g //添加调试信息
-O0 //优化级别 不优化
-Wall -Wextra:先用编译器把明显问题扫一遍(能省大量时间)
-fno-omit-frame-pointer(让栈回溯更稳定 --帧)
基础使用
valgrind ./a.out
内存泄漏代码例:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main() {
5 int *p = malloc(sizeof(int) * 10);
6 printf("%d\n", p[5]); // 未初始化读
7 return 0; // 泄漏:没 free
8 }
错误报告:
==5562== Memcheck, a memory error detector
==5562== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5562== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==5562== Command: ./a.out
==5562==
==5562== Conditional jump or move depends on uninitialised value(s)
==5562== at 0x4E9A8AA: vfprintf (vfprintf.c:1642)
==5562== by 0x4EA2EE5: printf (printf.c:33)
==5562== by 0x1086BC: main (test.c:6)
==5562==
==5562== Use of uninitialised value of size 8
==5562== at 0x4E9683B: _itoa_word (_itoa.c:179)
==5562== by 0x4E99EDD: vfprintf (vfprintf.c:1642)
==5562== by 0x4EA2EE5: printf (printf.c:33)
==5562== by 0x1086BC: main (test.c:6)
==5562==
==5562== Conditional jump or move depends on uninitialised value(s)
==5562== at 0x4E96845: _itoa_word (_itoa.c:179)
==5562== by 0x4E99EDD: vfprintf (vfprintf.c:1642)
==5562== by 0x4EA2EE5: printf (printf.c:33)
==5562== by 0x1086BC: main (test.c:6)
==5562==
==5562== Conditional jump or move depends on uninitialised value(s)
==5562== at 0x4E99FE4: vfprintf (vfprintf.c:1642)
==5562== by 0x4EA2EE5: printf (printf.c:33)
==5562== by 0x1086BC: main (test.c:6)
==5562==
==5562== Conditional jump or move depends on uninitialised value(s)
==5562== at 0x4E9AB1C: vfprintf (vfprintf.c:1642)
==5562== by 0x4EA2EE5: printf (printf.c:33)
==5562== by 0x1086BC: main (test.c:6)
==5562==
0
==5562==
==5562== HEAP SUMMARY:
==5562== in use at exit: 40 bytes in 1 blocks
==5562== total heap usage: 2 allocs, 1 frees, 1,064 bytes allocated
==5562==
==5562== LEAK SUMMARY:
==5562== definitely lost: 40 bytes in 1 blocks
==5562== indirectly lost: 0 bytes in 0 blocks
==5562== possibly lost: 0 bytes in 0 blocks
==5562== still reachable: 0 bytes in 0 blocks
==5562== suppressed: 0 bytes in 0 blocks
==5562== Rerun with --leak-check=full to see details of leaked memory
==5562==
==5562== For counts of detected and suppressed errors, rerun with: -v
==5562== Use --track-origins=yes to see where uninitialised values come from
==5562== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
==5562== total heap usage: 2 allocs, 1 frees, 1,064 bytes allocated
观察此行,可以发现堆内存分配了 2 次(共 1064 字节),但只释放了 1 次,导致程序退出时仍有 1 个内存块(40 字节)未被回收。
==5562== definitely lost: 40 bytes in 1 blocks
此行意为内存完全丢失,没有任何指针指向该内存空间,必须修复
==5562== Use of uninitialised value of size 8
==5562== at 0x4E9683B: _itoa_word (_itoa.c:179)
==5562== by 0x4E99EDD: vfprintf (vfprintf.c:1642)
==5562== by 0x4EA2EE5: printf (printf.c:33)
==5562== by 0x1086BC: main (test.c:6)
此段意为程序读取了一个 8 字节(指针的大小)的垃圾数据。
原因在于test.c的第六行打印了一个未初始化的变量导致 printf 在解析这个垃圾数字时触发了错误。
进阶参数
例:
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./app arg1 arg2
valgrind --leak-check=full ./app arg1 arg2
参数解释:
--leak-check=full:泄漏细节更全
--show-leak-kinds=all:显示 definitely/indirectly/possibly/ still reachable
--track-origins=yes:追踪未初始化值来源(慢一些,但非常值)
例:valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./a.out
==5626== HEAP SUMMARY:
==5626== in use at exit: 40 bytes in 1 blocks
==5626== total heap usage: 2 allocs, 1 frees, 1,064 bytes allocated
==5626==
==5626== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==5626== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5626== by 0x10869B: main (test.c:5)
==5626==
==5626== LEAK SUMMARY:
==5626== definitely lost: 40 bytes in 1 blocks
==5626== indirectly lost: 0 bytes in 0 blocks
==5626== possibly lost: 0 bytes in 0 blocks
==5626== still reachable: 0 bytes in 0 blocks
==5626== suppressed: 0 bytes in 0 blocks
==5626==
==5626== For counts of detected and suppressed errors, rerun with: -v
==5626== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
这里展示结果中的一段内容,可以发现给出的信息更加详细了
小结:
编译:
gcc -g -O0 -o app main.c
运行:
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./app

1万+

被折叠的 条评论
为什么被折叠?



