• linux下内存检测工具的使用和对比


    linux背后隐藏着各种丰富的工具,学会这些工具,让这些工具更好地服务于我们的项目开发,不仅可以提高工作的效率,而且可以增强个人技术力。

    参考:http://blog.chinaunix.net/uid-16135252-id-2752984.html

    内存检测工具有以下的几种:

    mtrace、memwatch、splint、valgrind

    对比:

       mtrace: 无需安装,使用时包含头文件mcheck.h,程序中调用mtrace和muntrace方法即可

       memwatch: 在需要检测的.c文件里面包含memwatch.h文件,编译的时候加上几个参数即可

       splint:需要下载源码并安装程序,通过标志和注释来获取想要的错误信息

       valgrind:提供不同的工具来实现不同功能的检测,需要编译源码

    各工具的使用

    一、mtrace工具

    mtrace是三款工具之中是最简单易用的,mtrace是一个C函數,在<mcheck.h>里声明及定义,函数原型为:

        void mtrace(void);

    其实mtrace是类似malloc_hook的malloc handler,只不过mtrace的handler function已由系统为你写好,但既然如此,系统又怎么知道你想将malloc/free的记录写在哪里呢?为此,调用mtrace()前要先设置MALLOC_TRACE环境变量:

        #include <stdlib.h>     ....    
       setenv("MALLOC_TRACE", "output_file_name", 1);     ...
      还可以通过export MALLOC_TRACE = output_file_name进行环境变量的设置

    「output_file_name」就是储存检测结果的文件的名称。

    但是检测结果的格式是一般人无法理解的,而只要有安装mtrace的话,就会有一名为mtrace的Perl script,在shell输入以下指令:

        mtrace [binary] output_file_name

    就会将output_file_name的內容转化成能被理解的语句,例如「No memory leaks」,「0x12345678 Free 10 was never alloc」诸如此类。

    例如以下有一函数:(暂且放下single entry single exit的原则)

       #include <stdio.h>    
       #include <stdlib.h>    
       #include <errno.h>    
       #include <mcheck.h>    
       int main()
       {        
            char *hello;            
            setenv("MALLOC_TRACE", "output", 1);        
            mtrace();        
           if ((hello = (char *) malloc(sizeof(char))) == NULL)
          {            
               perror("Cannot allocate memory.");          
              return -1;       
          }
            return 0;    
        }

    执行后,再用mtrace 将结果输出:

        …………………………………………
      ………………………………………………
        Memory not freed:     -----------------        Address     Size     Caller     0x08049a90      0x1  at 0x80483fe

    最后一行标明有一个大小为1 byte的内存尚未释放,应该就是指hello

        若我们把该段内存释放:

        #include <stdio.h>    
        #include <stdlib.h>    
       #include <errno.h>    
       #include <mcheck.h>    
      int main()
      {        
            char *hello;            
            setenv("MALLOC_TRACE", "output", 1);        
            mtrace();        
            if ((hello = (char *) malloc(sizeof(char))) == NULL)
           {            
                perror("Cannot allocate memory.");            
                return -1;        
           }
     
                free(hello);        
                return 0;    
      }

    结果如下:

             ……………………
             ……………………
             No memory leaks.

    mtrace的原理是记录每一对malloc-free的执行,若每一个malloc都有相应的free,则代表没有内存泄露,对于任何非malloc/free情況下所发生的内存泄露问题,mtrace并不能找出来。

    二、memwatch工具

    在三种检测工具当中,设置最简单的算是memwatch,和dmalloc一样,它能检测未释放的内存、同一段内存被释放多次、位址存取错误及不当使用未分配之内存区域,溢出和下溢等错误。请在http://www.linkdata.se/sourcecode.html下载最新版本的Memwatch。  

    步骤:

    1. 确保被测工程中有memwatch.c和memwatch.h文件,
    1. 源码中每个.c文件中都include头文件memwatch.h
    1. 编译代码,gcc后添加-DMEMWATCH -DMW_STDIO或者-DMEMWATCH_STDIO,还有memwatch.c文件,例如:

                     gcc -DMEMWATCH -DMW_STDIO test.c memwatch.c -o test

    1. 运行生成的可执行文件,程序运行结束后,生成的log文件名为memwatch.log,而且在程序执行期间,所有错误提示都会显示在stdout上

                      如果未生成上述文件,则会写入memwatNN.log文件,NN01~99,如果还未成功,则放弃写log文件。

        :memwatch会使系统速度减慢

     

        三、splint的使用

             1.splint是静态代码检测工具,可以检查包括:

                    1)Null Dereferences:针对空指针

                    2)Undefined Values:未初始化数据

                    3)Types:转化类型不一致

                    4)Memory Management:内存管理检测,如内存泄露

                    5)sharing:共享存储空间安全性检测

                    6)Function Interfaces:函数接口检测(参数传递等)

                    7)Control Flow:函数执行分支检测

                    8)Buffer Sizes:缓冲区边界检查

                    9)Completeness:完整性检查,包括未使用变量、函数等

                    10)Macros(宏隐患检测等)

     

              2.源码包安装:

                 #tar zxvf splint-3.1.2.src.tgz

                 #cd splint-3.1.2

                 #mkdir /usr/local/splint

                 #./configure --prefix=/usr/local/splint

                 #make

                  #make install

                  #vi ~/.bashrc    (或者 sudo gedit ~/.bashrc) ~目录是/root

                  向其中添加以下内容:

                      export LARCH_PATH=/usr/local/splint/share/splint/lib

                      export LCLIMPORTDIR=/usr/local/splint/share/splint/import

     

                  #source ~/.bashrc

                  #export PATH=/usr/local/splint/bin/splint:$PATH

               到此,splint源码安装完成。

        3.splint提供了三种方式进行检查的控制,分别是flags标志、 .splintrc配置文件和格式化注释。

          flags: splint支持几百个标志用来控制检查和消息报告,使用时标志前加‘+’或‘-’,‘+’标志开启这个标志,‘-’表示关闭此标志。下面例子展示了flags标志的用法:

          splint -showcol a.c //在检测a.c时,告警消息中列数不被打印

          splint -varuse a.c //在检测a.c时,告警消息中未使用变量告警不被打印

          .splintrc配置文件: .splintrc文件中对一些flags做了默认的设定,命令行中指定的flags会覆盖.splintrc文件中的标志。

        格式化注释:格式化注释提供一个类型、变量或函数的额外的信息,可以控制标志设置,增加检查效果。所有格式化注释都以/*@开始,@*/结束,比如在函数参数前加/*@null@*/,表示该参数可能是NULL,做检测时,splint会加强对该参数的值的检测。

     

     

    四. valgrind使用:

     

    步骤:

    1tar -xf valgrind-3.9.0.tar.bz2

    2./configure

    3make

    4make install(如果失败,改用root权限)

    5valgrind ls -l(检查是否正常工作,如果出错,按照提示安装相应文件)

     

    下面的工具是valgrind安装时的标准配置:

    Memcheck:用于检测内存错误。它帮助cc++的程序更正确。

    Cachegrind:用于分析cache和分支预测。它帮助程序执行得更快。

    Callgrind:用于函数调用的分析。

    Helgrind:用于分析多线程。

    DRD:也用于分析多线程。与Helgrind类似,但是用不同的分析技术,所以可以检测不同的问题。

    Massif:用于分析堆。它帮助程序精简内存的使用。

    SGcheck:检测栈和全局数组溢出的实验性工具,它和Memcheck互补使用。

     

    --leak-check=yes打开内存泄露检测细节

    --tool=helgrind使用Helgrind工具检测线程错误

     

    假设hello是可执行程序:可能的使用方法如下

    valgrind --leak-check=yes ./hello

    或者valgrind ./hello

    终端上显示检测信息。

     

     

     

  • 相关阅读:
    EasyNVR播放HLS协议时ts文件报错404是什么问题?
    【操作步骤】EasyNVR硬件设备如何设置通电不自动启动?
    C#实现QQ接口软件QQ的HTTP接口协议探究
    第一篇随笔
    Extjs继承相关
    Montgomery乘法介绍
    中国商用密码杂凑算法标准SM3算法(数字签名)
    c语言链接动态库dll
    环、商环、整数环
    大数据挖掘技术及应用(复习重点)
  • 原文地址:https://www.cnblogs.com/honglihua8688/p/3727944.html
Copyright © 2020-2023  润新知