(这里我的安装环境是Ubuntu)
打开终端,确保你的包列表是最新的。运行以下命令来更新包列表:
sudo apt update
安装 valgrind
。运行以下命令来安装 valgrind
:
sudo apt install valgrind
安装完成后,验证 valgrind
是否成功安装。在终端中运行以下命令来检查 valgrind
的版本信息:
valgrind --version
这应该会显示 valgrind
的版本信息,确认安装成功。
- #include
- void f(void)
- {
- int* x = malloc(10 * sizeof(int));
- x[10]=0; //问题1:数组下标越界
- //问题2:内存没有释放
- }
-
- int main(void)
- {
- f();
- return 0;
- }
编译:
# gcc -o demo demo.o
利用Valgrind检测:
最常用的检测命令:valgrind --tool=memcheck --leak-check=full ./demo
其中memcheck的常见选项有:
设置内存泄漏检查的行为级别:
--leak-check=no|summary|full 在退出时是否查找内存泄露。默认值为summary
设置内存泄漏报告解析级别:
--leak-resolution=low|med|high how much bt merging in leak check [low]
设置是否报告那些虽然仍然可以访问但未被显式释放的内存块:
--show-reachable=no|yes show reachable blocks in leak check? [no]
输出结果:
==31749== Memcheck, a memory error detector
==31749== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31749== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==31749== Command: ./demo
==31749==
==31749== Invalid write of size 4
==31749== at 0x10916B: f (demo.c:5)
==31749== by 0x109180: main (demo.c:11)
==31749== Address 0x4a9a068 is 0 bytes after a block of size 40 alloc'd
==31749== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==31749== by 0x10915E: f (demo.c:4)
==31749== by 0x109180: main (demo.c:11)
==31749==
==31749==
==31749== HEAP SUMMARY:
==31749== in use at exit: 40 bytes in 1 blocks
==31749== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==31749==
==31749== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31749== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==31749== by 0x10915E: f (demo.c:4)
==31749== by 0x109180: main (demo.c:11)
==31749==
==31749== LEAK SUMMARY:
==31749== definitely lost: 40 bytes in 1 blocks
==31749== indirectly lost: 0 bytes in 0 blocks
==31749== possibly lost: 0 bytes in 0 blocks
==31749== still reachable: 0 bytes in 0 blocks
==31749== suppressed: 0 bytes in 0 blocks
==31749==
==31749== For lists of detected and suppressed errors, rerun with: -s
==31749== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
无效写入:
Invalid write of size 4
:
这部分告诉你发生了一个大小为 4 字节的无效写入。这通常表示你的程序试图写入一个内存区域,但它没有权限这样做。
at 0x10916B: f (demo.c:5)
:
这一行告诉你在程序的demo.c
文件的第 5 行的函数f
中发生了无效写入。
by 0x109180: main (demo.c:11)
:
这一行告诉你问题是由程序的demo.c
文件的第 11 行的main
函数触发的,它调用了函数f
。
Address 0x4a9a068 is 0 bytes after a block of size 40 alloc'd
:这部分指出了问题的具体位置。它说在地址0x4a9a068
处进行了无效写入,而这个地址是在一个大小为 40 字节的内存块之后的 0 字节处。这个信息非常重要,因为它告诉你问题的来源是在一个之前通过malloc
函数分配的内存块之后的部分。
at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
:这部分告诉你在malloc
函数内部的某个地方发生了问题。malloc
是分配内存的标准函数,所以这一行的意思是问题出现在分配内存的过程中。
by 0x10915E: f (demo.c:4)
:这一行告诉你问题是由程序的demo.c
文件的第 4 行的函数f
触发的。通常,在f
函数中发生了malloc
调用,它试图分配一块内存,但似乎有问题。
by 0x109180: main (demo.c:11)
:这一行告诉你问题是由程序的demo.c
文件的第 11 行的main
函数触发的,它调用了函数f
内存泄漏:
HEAP SUMMARY
:这一部分提供了有关程序在退出时内存的摘要信息。它告诉我们,程序在退出时仍然使用了 40 字节的堆内存,只进行了一次分配操作,没有释放。
LEAK SUMMARY
:这一部分提供了关于内存泄漏的总结信息。在这种情况下,它指出了程序中的一个内存泄漏:40 字节的内存在程序退出时被泄漏了。泄漏信息包括“definitely lost”(确定泄漏)。
综合来看,该程序文件的第 5 行的函数 中发生了一个无效的内存写入,它写入了一个之前分配的内存块之后的 0 字节。
此外,程序还存在一个内存泄漏,40 字节的内存在程序退出时未被释放。
1、比较简单的就是根据Visual Studio中的诊断工具,可视化地查看进程内存的情况
2、使用VLD工具,其安装和使用参考:VS 2022 安装vld内存泄漏检测工具_vs2022内存泄漏检测vld-2.5.1-setup_2_你虞姐的博客-CSDN博客
内存检测工具vld安装配置和使用 Visual Leak Detector_哔哩哔哩_bilibili
3、使用CRT库
头文件 加上 #include
在main函数最后面一行,加上一句_CrtDumpMemoryLeaks()。调试程序,自然关闭程序让其退出,查看输出:
输出这样的格式{453}normal block at 0x02432CA8,868 bytes long
被{}包围的453就是我们需要的内存泄漏定位值,868 bytes long就是说这个地方有868比特内存没有释放。
定位代码位置,在main函数第一行加上_CrtSetBreakAlloc(453);意思就是在申请453这块内存的位置中断。然后调试程序,程序中断了,查看调用堆栈。