1、massif,堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块、堆管理块和栈的大小。它能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能加速我们的程序运行,减少程序停留在交换区中的几率。.extension。可以利用core提供的功能,自己编写特定的内存调试工具。2).valgrind的使用Valgrindvalgrind-optionsyour-prog your-prog-options选项作用-h/-help显示帮助信息-version显示valgrind内核版本-q/-quiet安静的运行,只打印错误信息-v /-verbose打印更详细的信息-tool=defa
2、ult : memcheck运行valgrind中的工具,默认memcheck.-leak-check=no|summary|full 要求对leak列出详细信息default:summary-log-file=Path+日志信息文件3).使用示例.未释放内存,数组越界.sample.c#include void fun() int *p = (int *)malloc(10*sizeof(int); p10=0;int main(int argc , char *argv) fun(); return 0;1.编译:gcc g sample.c o sample2.使用valgrind:va
3、lgrind -leak-check=full ./sample输出信心分析如下图所示:示例程序中有两个问题,一是fun()函数中动态申请的堆内存没有释放。二是对堆内存的访问越界。.使用未初始化的内存。badloop.cstdio.hint main(void) int a5; int i ,s; a0 = a1 = a2 = a3 = a4 =0; for(i = 0 ; i char x50; int i; 50; xi = i+1; strncpy(x+20 , x , 20); strncpy(x+20 , x , 21); strncpy(x , x+20 , 20); strncp
4、y(x , x+20 , 21); x39 = 0; strcpy(x , x+20); x39 = 39; x40 = g+gbadlap.c o badlap2.使用valgrind -leak-check=full ./badlap代码画红线部分地址相差20,但是拷贝长度却是21,这样就会覆盖之前的值。Valgrind也很精确的检测出了这一点。.动态内存管理错误。badmac.cpp常见的内存动态管理错误:申请和释放不一致(malloc/alloc/realloc申请用free。new用delete)申请和释放不匹配,申请了多少内存,在使用完成后就要释放多少。如果没有释放或者少释放了就是
5、内存泄漏,多释放了也会产生问题。释放后仍然读写。 char *p = (char *)malloc(10); char *pt = p; 10 ; pi = 65+i; delete p; pt1 = x free(pt);g+ gbadmac.c o badmac2.使用valgrind -leak-check=full ./badmac由图可以看出,valgrind准确定位出这三个错误。.内存泄漏内存泄漏(Memory leak)指的是在程序中动态申请的内存,使用完成后即没有释放,又无法被程序的其它部分访问。Tree.h#ifndef _BADLEAK_#define _BADLEAK_t
6、ypedef struct _node struct _node *l; struct _node *r; char v;node;node *mk(node *l , node *r , char val);void nodefr(node *n);#endifTree.cpp#include tree.hnode *mk(node *l , node *r , char val) node *f = (node *)malloc(sizeof(node); f-l = l;r = r;v = val; return f;void nodefr(node *n) if(n) nodefr(n
7、-l);r); free(n);Badleak.cpp node *tree1 , *tree2 , *tree3;testn); tree1 = mk(mk(mk(0,0,3),0,21 tree2 = mk(0,mk(0,mk(0,0,6),54 tree3 = mk(mk(tree1,tree2,87 Makefilebadleak:badleak.o tree.o g+ -o badleak badleak.o tree.obadleak.o:badleak.cpp g+ -g -c badleak.cpptree.o:tree.cpp g+ -g -c tree.cppclean:
8、rm -rf *.o rm -rf badleak至此,valgrind常用的方法已总结完毕,置于valgrind的其它工具使用在此就不一 一列举。四静态代码检查Splint静态程序分析(static program analysis):静态程序分析是指使用自动化工具软件对程序源代码进行检查,以分析程序行为的技术,应用程序的正确性、安全缺陷检测、程序优化等。它的特点是不执行程序。1.Splint的检测范围:可能的空指针在释放内存之后使用了该指针赋值次序问题拼写错误被零除失败的case语句(遗漏了break语句)不可移植的代码宏定义参数没用圆括号符号的丢失异常的表达式变量没有初始化转换类型不一致
9、可疑的判断语句(例如:if(x=0)Printf/scanf的格式检查2.Splint的使用在Linux命令行下,splint的使用很简单,检测文件*.c,用法如下:splint *.c检查控制 splint提供了三种方式可进行检查的控制,分别是.splintrc配置文件、flags标志和格式化注释。flags:splint支持几百个标志用来控制检查和消息报告,使用时标志前加+或-,+标志开启这个标志,-表示关闭此标志,下面例子展示了flags标志的用法:splint -showcol a.c /在检测a.c时,告警消息中列数不被打印splint -varuse a.c /在检测a.c时,告警
10、消息中未使用变量告警不被打印.splintrc配置文件:在使用源码安装splint之后,.splintrc文件将被安装在主目录下,.splintrc文件中对一些标志作了默认的设定,命令行中指定的flags标志会覆盖.splintrc文件中的标志。格式化注释:格式化注释提供一个类型、变量或函数的格外的信息,可以控制标志设置,增加检查效果,所有格式化注释都以/*开始,*/结束,比如在函数参数前加/*null*/,表示该参数可能是NULL,做检测时,splint会加强对该参数的值的检测。3.使用示例.认识splint输出的警告消息int func_splint_msg1(void) int a;in
11、t func_splint_msg2(void) int *a = (int*)malloc(sizeof(int); a = NULL;直接运行:splint sample.c使用空指针null_point.cint func_null_point(void) int *a = NULL; return *a;splint null_point.c.转换类型不一致问题types.cvoid splint_types(void) short a = 0; long b = 32768; a = b; return ;splint types.c.内存管理memory_managment.c/当
12、有其他指针引用当时候,释放一块空间void memory_management(void) int *a = (int *)malloc(sizeof(int); int *b = a; free(a); *b = 0;splint memory_managment.c a = NULL;缓存边界buffersize.cvoid bounds1(void ) int a10; a10=0;splint +bounds buffersize.cvoid bounds2(char *str) char *tmp = getenv(HOME if(tmp != NULL) strcpy(str , tmp);警告指出,在使用strcpy(str,tmp)时可能出现越界错误,因为str大小未知。五Cppcheck C/C+静态代码分析工具这个工具可以在windows下安装。双击即可安装。安装后启动界面为:Cppcheck检测的是整个目录。单击即可打开一个目录。示例:sample目录下有一个sample.c代码如下:检测结果:关于cppcheck用法这里不再一一赘述。小结: 代码检查工具有很多,通过我多方搜索,就觉得这三款还不错。有了这些工具的帮助虽然可以提高我们程序运行的质量。但是代码的编写还要靠各位大神的细心和耐心。写出优质的代码,让这些检查工具无可检查。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1