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


    Valgrind

    Valgrind安装

    (这里我的安装环境是Ubuntu

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

      sudo apt update

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

      sudo apt install valgrind

    3. 安装完成后,验证 valgrind 是否成功安装。在终端中运行以下命令来检查 valgrind 的版本信息:

      valgrind --version

      这应该会显示 valgrind 的版本信息,确认安装成功。

    测试程序

    1. #include
    2. void f(void)
    3. {
    4. int* x = malloc(10 * sizeof(int));
    5. x[10]=0; //问题1:数组下标越界
    6. //问题2:内存没有释放
    7. }
    8. int main(void)
    9. {
    10. f();
    11. return 0;
    12. }

    编译: 

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

  • 相关阅读:
    智牛股项目--02
    SSM运动器材共享平台毕业设计源码201816
    大数据ClickHouse(八):MergeTree系列表引擎之MergeTree(重点掌握)
    【图像分割】基于matlab直方图的自适应阈值方法分割前景与背景【含Matlab源码 2144期】
    flutter 适配屏幕宽高工具
    Nginx入门到精通1-nginx基础及环境搭建
    【Verilator】 1 简明教程
    《基于区块链的数据资产评估实施指南》技术研讨会成功召开
    18.示例程序(编码器接口测速)
    Dubbo—Admin 整体架构与安装步骤
  • 原文地址:https://blog.csdn.net/weixin_42809675/article/details/133300173