【C++基础】内存泄漏检测——Valgrind、VLD、RTC

Valgrind

Valgrind安装

(这里我的安装环境是Ubuntu)

  1. 打开终端,确保你的包列表是最新的。运行以下命令来更新包列表:

    sudo apt update

  2. 安装 valgrind。运行以下命令来安装 valgrind

    sudo apt install valgrind

  3. 安装完成后,验证 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)
 

结果分析

无效写入:

  1. Invalid write of size 4
    这部分告诉你发生了一个大小为 4 字节的无效写入。这通常表示你的程序试图写入一个内存区域,但它没有权限这样做。

  2. at 0x10916B: f (demo.c:5)
    这一行告诉你在程序的 demo.c 文件的第 5 行的函数 f 中发生了无效写入。

  3. by 0x109180: main (demo.c:11)
    这一行告诉你问题是由程序的 demo.c 文件的第 11 行的 main 函数触发的,它调用了函数 f

  4. Address 0x4a9a068 is 0 bytes after a block of size 40 alloc'd:这部分指出了问题的具体位置。它说在地址 0x4a9a068 处进行了无效写入,而这个地址是在一个大小为 40 字节的内存块之后的 0 字节处。这个信息非常重要,因为它告诉你问题的来源是在一个之前通过 malloc 函数分配的内存块之后的部分。

  5. at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so):这部分告诉你在 malloc 函数内部的某个地方发生了问题。malloc 是分配内存的标准函数,所以这一行的意思是问题出现在分配内存的过程中。

  6. by 0x10915E: f (demo.c:4):这一行告诉你问题是由程序的 demo.c 文件的第 4 行的函数 f 触发的。通常,在 f 函数中发生了 malloc 调用,它试图分配一块内存,但似乎有问题。

  7. by 0x109180: main (demo.c:11):这一行告诉你问题是由程序的 demo.c 文件的第 11 行的 main 函数触发的,它调用了函数 f

 内存泄漏:

  1. HEAP SUMMARY:这一部分提供了有关程序在退出时内存的摘要信息。它告诉我们,程序在退出时仍然使用了 40 字节的堆内存,只进行了一次分配操作,没有释放。

  2. LEAK SUMMARY:这一部分提供了关于内存泄漏的总结信息。在这种情况下,它指出了程序中的一个内存泄漏:40 字节的内存在程序退出时被泄漏了。泄漏信息包括“definitely lost”(确定泄漏)。

综合来看,该程序文件的第 5 行的函数 中发生了一个无效的内存写入,它写入了一个之前分配的内存块之后的 0 字节。

此外,程序还存在一个内存泄漏,40 字节的内存在程序退出时未被释放。

Windows平台下的内存检测方法

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这块内存的位置中断。然后调试程序,程序中断了,查看调用堆栈。

你可能感兴趣的:(c++)