linux背后隐藏着各种各种丰富的宝藏,找到这些工具,学会这些工具,让这些工具更好地服务于我们的项目开发,不仅可以提高工作的效率,而且可以增强个人技术力。所以围绕在MK1阶段和MK23阶段,有哪些工具可以辅助我们的工作,我们展开了此次技术调查。
[应用范围]
MK1阶段和MK23阶段的内存检测
[正文]
对比:
mtrace: 不需要安装,使用时包含一个头文件,程序中在需要的调用mtrace和muntrace方法即可
memwatch: 在需要检测的.c文件里面包含memwatch.h文件,编译的时候加上几个参数即可
splint:需要下载源码并安装程序,通过标志和注释来获取想要的错误信息
valgrind:提供不同的工具来实现不同功能的检测,需要编译源码
使用:
一. mtrace使用方法:
mtrace只能检测malloc,realloc和free引发的错误。
用法如下:
1. 定义宏export MALLOC_TRACE=<malloc_trace_filename>
例如:MALLOC_TRACE=mlog.txt
如果不定义宏或者不能定义宏,使用setenv函数,下面是setenv函数原型:
#include <stdlib.h>
--int setenv(const char *name, const char *value, int overwrite)
该函数是用来添加或者改变一个环境变量,name是变量名,value是值,如果变量已经存在并且overwrite为0,不改变变量值,如果overwrite不为0,则使用环境变量的新值覆盖旧值。
一个使用的例子:setenv("MALLOC_TRACE", "mlog.txt", 1);
2. 在.c文件中引用#include <mcheck.h>
3. 在开始申请内存之前,调用mtrace();
4. 执行编译后生成的可执行文件,如果程序结束,对于生成的mlog.txt,使用mtrace mlog.txt 或者 mtrace <可执行文件> mlog.txt
5. 如果程序会一直运行,在程序适当的地方调用muntrace函数,就会生成log文件
如果对一块内存free多次,程序运行被打断,终端打印出错误。
一个简单的例子:
#include <stdio.h>
#include <mcheck.h>
#include <stdlib.h>
int main()
{
setenv("MALLOC_TRACE", "mlog.txt", 1);
char *p;
mtrace();
p = (char *)malloc(4);
p = (char *)malloc(5);
while( 1 )
{
sleep(4);
muntrace();
}
return 0;
}
二. memwatch使用方法:
memwatch可以检测:未释放的内存,同一段内存被释放多次和使用未分配内存区域,溢出和下溢等错误;
右边是使用memwatch要用到的源码。
步骤:
-
确保被测工程中有memwatch.c何memwatch.h文件,
-
源码中每个.c文件中都include头文件memwatch.h,
-
编译代码,gcc后添加-DMEMWATCH 和 -DMW_STDIO(或者-DMEMWATCH_STDIO),还有memwatch.c文件,
-
运行生成的可执行文件,程序运行结束后,生成的log文件名为memwatch.log,如果未生成上述文件,则会写入memwatNN.log文件,NN为01~99,如果还未成功,则放弃写log文件。
注:memwatch会使系统速度减慢
三. splint使用:
splint是静态代码检测工具,可以检查包括:
Null Dereferences:针对空指针
Undefined Values:未初始化数据
Types:转化类型不一致
Memory Management:内存管理检测,如内存泄露
sharing:共享存储空间安全性检测
Function Interfaces:函数接口检测(参数传递等)
Control Flow:函数执行分支检测
Buffer Sizes:缓冲区边界检查
Completeness:完整性检查,包括未使用变量、函数等
还有Macros(宏隐患检测等)
还有其他的应用。
源码包安装:
#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源码安装完成。
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使用:
步骤:
1:tar -xf valgrind-3.9.0.tar.bz2
2:./configure
3:make
4:make install(如果失败,改用root权限)
5:valgrind ls -l(检查是否正常工作,如果出错,按照提示安装相应文件)
下面的工具是valgrind安装时的标准配置:
Memcheck:用于检测内存错误。它帮助c和c++的程序更正确。
Cachegrind:用于分析cache和分支预测。它帮助程序执行得更快。
Callgrind:用于函数调用的分析。
Helgrind:用于分析多线程。
DRD:也用于分析多线程。与Helgrind类似,但是用不同的分析技术,所以可以检测不同的问题。
Massif:用于分析堆。它帮助程序精简内存的使用。
SGcheck:检测栈和全局数组溢出的实验性工具,它和Memcheck互补使用。
--leak-check=yes打开内存泄露检测细节
--tool=helgrind使用Helgrind工具检测线程错误
假设hello是可执行程序:可能的使用方法如下
valgrind --leak-check=yes ./hello
或者valgrind ./hello
终端上显示检测信息。