linux下的测试工具真是少之又少,还不好用,最近试用了memwatch,感觉网上的介绍不太好,所以放在这里跟大家分享 。其实大部分都是看的帮助,很多地方翻译得不好还有错,请原谅指出最好看原文。如果转载或引用,请注明我的博客地址,谢谢。

1介绍

MemWatch由 Johan Lindh 编写,是一个开放源代码 C 语言内存错误检测工具。MemWatch支持 ANSI C,它提供结果日志纪录,能检测双重释放(double-free)、错误释放(erroneous free)、内存泄漏(unfreed memory)、溢出(Overflow)、下溢(Underflow)等等。

1.1 MemWatch的内存处理

MemWatch将所有分配的内存用0xFE填充,所以,如果你看到错误的数据是用0xFE填充的,那就是你没有初始化数据。例外是calloc(),它会直接把分配的内存用0填充。

MemWatch将所有已释放的内存用0xFD填充(zapped with 0xFD).如果你发现你使用的数据是用0xFD填充的,那你就使用的是已释放的内存。在这种情况,注意MemWatch会立即把一个"释放了的块信息"填在释放了的数据前。这个块包括关于内存在哪儿释放的信息,以可读的文本形式存放,格式为"FBI<counter>filename(line)"。如:"FBI<267>test.c(12)".使用FBI会降低free()的速度,所以默认是关闭的。使用mwFreeBufferInfo(1)开启。

为了帮助跟踪野指针的写情况,MemWatch能提供no-mans-land(NML)内存填充。no-mans-land将使用0xFC填充.当no-mans-land开启时,MemWatch转变释放的内存为NML填充状态。

1.2初始化和结束处理

一般来说,在程序中使用MemWatch的功能,需要手动添加mwInit()进行初始化,并用对应的mwTerm ()进行结束处理。

当然,如果没有手动调用mwInit(),MemWatch能自动初始化.如果是这种情形,memwatch会使用atext()注册mwTerm()用于atexit-queue.对于使用自动初始化技术有一个告诫;如果你手动调用atexit()以进行清理工作,memwatch可能在你的程序结束前就终止。为了安全起见,请显式使用mwInit()和mwTerm().

涉及的函数主要有:

mwInit()   mwTerm()    mwAbort()

1.3 MemWatch的I/O操作

对于一般的操作,MemWatch创建memwatch.log文件。有时,该文件不能被创建;MemWatch会试图创建memwatNN.log文件,NN在01~99之间。

如果你不能使用日志,或者不想使用,也没有问题。只要使用类型为"void func(int c)"的参数调用mwSetOutFunc(),然后所有的输出都会按字节定向到该函数.

当ASSERT或者VERIFY失败时,MemWatch也有Abort/Retry/Ignore处理机制。默认的处理机制没有I/O操作,但是会自动中断程序。你可以使用任何其他Abort/Retry/Ignore的处理机制,只要以参数"void func(int c)"调用mwSetAriFunc()。后面在1.2使用一节会详细讲解。

涉及的函数主要有:

mwTrace()          mwPuts()        mwSetOutFunc() mwSetAriFunc()

mwSetAriAction()   mwAriHandler()  mwBreakOut()

1.4 MemWatch对C++的支持

可以将MemWatch用于C++,但是不推荐这么做。请详细阅读memwatch.h中关于对C++的支持。

 2使用

2.1为自己的程序提供MemWatch功能

Ø       在要使用MemWatch的.c文件中包含头文件"memwatch.h"

Ø       使用GCC编译(注意:不是链接)自己的程序时,加入-DMEMWATCH -DMW_STDIO
如:gcc -DMEMWATCH -DMW_STDIO –o test.o–c test1.c

2.2使用MemWatch提供的功能

1)在程序中常用的MemWatch功能有:

Ø        mwTRACE( const char* format_string, ... );
或TRACE( const char* format_string, ... );

Ø        mwASSERT( int, const char*, const char*, int )
或ASSERT( int, const char*, const char*, int )

Ø        mwVERIFY( int, const char*, const char*, int )
或VERIFY( int, const char*, const char*, int )

Ø        mwPuts( const char* text )

Ø        ARI机制(mwSetAriFunc(int (*func)(const char *)),
          mwSetAriAction(int action),
          mwAriHandler( const char* cause ))

Ø        mwSetOutFunc(void (*func)(int))

Ø        mwIsReadAddr(const void *p, unsigned len )

Ø        mwIsSafeAddr(void *p, unsigned len )

Ø        mwStatistics( int level )

Ø        mwBreakOut( const char* cause)

2)mwTRACE,mwASSERT,mwVERIFY和mwPuts顾名思义,就不再赘述。仅需要注意的是,Memwatch定义了宏TRACE,   ASSERT 和 VERIFY.如果你已使用同名的宏,memwatch2.61及更高版本的memwatch不会覆盖你的定义。MemWatch2.61及以后,定义了mwTRACE, mwASSERT和 mwVERIFY宏,这样,你就能确定使用的是memwatch的宏定义。2.61版本前的memwatch会覆盖已存在的同名的TRACE, ASSERT和 VERIFY定义。

当然,如果你不想使用MemWatch的这几个宏定义,可以定义MW_NOTRACE, MW_NOASSERT和 MW_NOVERIFY宏,这样MemWatch的宏定义就不起作用了。所有版本的memwatch都遵照这个规则。

3)ARI机制即程序设置的“Abort, Retry, Ignore选择陷阱。

mwSetAriFunc:

设置“Abort, Retry, Ignore”发生时的MemWatch调用的函数.当这样设置调用的函数地址时,实际的错误消息不会打印出来,但会作为一个参数进行传递。

如果参数传递NULL,ARI处理函数会被再次关闭。当ARI处理函数关闭后, meewatch会自动调用有mwSetAriAction()指定的操作。

正常情况下,失败的ASSERT() or VERIFY()会中断你的程序。但这可以通过mwSetAriFunc()改变,即通过将函数"int myAriFunc(const char *)"传给它实现。你的程序必须询问用户是否中断,重试或者忽略这个陷阱。返回2用于Abort, 1用于Retry,或者0对于Ignore。注意retry时,会导致表达式重新求值.

MemWatch有个默认的ARI处理器。默认是关闭的,但你能通过调用mwDefaultAri()开启。注意这仍然会中止你的程序除非你定义MEMWATCH_STDIO允许MemWatch使用标准C的I/O流。

同时,设置ARI函数也会导致MemWatch不将ARI的错误信息写向标准错误输出,错误字符串而是作为'const char *'参数传递到ARI函数.

mwSetAriAction:

如果没有ARI处理器被指定,设置默认的ARI返回值。默认是MW_ARI_ABORT

mwAriHandler:

这是个标准的ARI处理器,如果你喜欢就尽管用。它将错误输出到标准错误输出,并从标准输入获得输入。

mwSetOutFunc:

将输出转向调用者给出的函数(参数即函数地址)。参数为NULL,表示把输出写入日志文件memwatch.log.

mwIsReadAddr:

检查内存是否有读取的权限

mwIsSafeAddr:

检查内存是否有读、写的权限

mwStatistics:

设置状态搜集器的行为。对应的参数采用宏定义。

#define MW_STAT_GLOBAL 0       /* 仅搜集全局状态信息 */

#define MW_STAT_MODULE 1       /* 搜集模块级的状态信息 */

#define MW_STAT_LINE   2       /* 搜集代码行级的状态信息 */

#define MW_STAT_DEFAULT 0      /* 默认状态设置 */

mwBreakOut:

当某些情况MemWatch觉得中断(break into)编译器更好时,就调用这个函数.如果你喜欢使用MemWatch,那么可以在这个函数上设置执行断点。

其他功能的使用,请参考源代码的说明。

2.3分析日志文件

日志文件memwatch.log中包含的信息主要有以下几点:

Ø        测试日期

Ø        状态搜集器的信息

Ø        使用MemWatch的输出函数或宏(如TRACE等)的信息。

Ø        MemWatch捕获的错误信息

Ø        内存使用的全局信息统计,包括四点:1)分配了多少次内存 2)最大内存使用量3)分配的内存总量 4)为释放的内存总数

MemWatch捕获的错误记录在日志文件中的输出格式如下:

message: <sequence-number> filename(linenumber), information

2.4注意事项

mwInit()和mwTerm()是对应的.所以使用了多少次mwInit(),就需要调用多少次

mwTerm()用于终止MemWatch.

如果在流程中捕获了程序的异常中断,那么需要调用mwAbort()而不是

mwTerm()。即使有显示的调用mwTerm(),mwAbort()也将终止MemWatch。

MemWatch不能确保是线程安全的。如果你碰巧使用Wind32或者你使用了线程,作为2.66,是初步支持线程的。定义WIN32或者MW_PTHREADS以明确支持线程。这会导致一个全局互斥变量产生,同时当访问全局内存链时,MemWatch会锁定互斥变量,但这远不能证明是线程安全的。

3结论

从MemWatch的使用可以得知,无法用于内核模块。因为MemWatch自身就使用了应用层的接口,而不是内核接口。但是,对于普通的应用层程序,我认为还是比较有用,并且是开源的,可以自己修改代码实现;它能方便地查找内存泄漏,特别是提供的接口函数简单易懂,学习掌握很容易,对应用层程序的单元测试会较适用。

Memwatch使用说明

Memwatch使用说明相关推荐

  1. Memwatch简介

    Memwatch简介 在三种检测工具当中,设置最简单的算是memwatch,和dmalloc一样,它能检测未释放的内存.同一段内存被释放多次.位址存取错误及不当使用未分配之内存区域.请往http:// ...

  2. Linux C 编程内存泄露检测工具(二):memwatch

    Memwatch简介 在三种检测工具当中,设置最简单的算是memwatch,和dmalloc一样,它能检测未释放的内存.同一段内存被释放多次.位址存取错误及不当使用未分配之内存区域.请往http:// ...

  3. 利用工具定位内存泄漏问题 valgrind memwatch dmalloc

    内存泄漏定位工具 内存debug有比较多的方法,首先可以参看如下的wiki,查看大概都有哪些方式,再根据其有缺点选用,适合自己需要的方式. Memory Debuggers https://elinu ...

  4. abaqus高性能服务器怎么用,高性能计算平台ABAQUS任务调度使用说明作者陈林E-Mailchenlin.PDF...

    高性能计算平台ABAQUS任务调度使用说明作者陈林E-Mailchenlin.PDF 高性能计算平台ABAQUS 任务调度使用说明 作者:陈林 E-Mail:chenlin@ 日期:2017-1-10 ...

  5. linux 文件拷贝并替换,Linux_cmd replace 文件替换使用说明,帮助信息: 复制代码 代码如 - phpStudy...

    cmd replace 文件替换使用说明 帮助信息: 复制代码 代码如下: 替换文件. REPLACE [drive1:][path1]filename [drive2:][path2] [/A] [ ...

  6. Simple Dynamic Strings(SDS)源码解析和使用说明二

    在<Simple Dynamic Strings(SDS)源码解析和使用说明一>文中,我们分析了SDS库中数据的基本结构和创建.释放等方法.本文将介绍其一些其他方法及实现.(转载请指明出于 ...

  7. Delphi开发的IOCP测试Demo以及使用说明。

    Delphi开发的IOCP,此为压力测试Demo和使用说明.

  8. oracle database link mysql_oracle database link使用说明

    oracle database link使用说明 作用: 将多个oracle数据库逻辑上看成一个数据库,也就是说在一个数据库中可以操作另一个数据库中的对象. 简易语法: CREATE [PUBLIC] ...

  9. 序列拼接工具Bowtie使用说明

    序列拼接工具Bowtie使用说明 2011-06-08 ~ ADMIN Bowtie是一个超级快速的,较为节省内存的短序列拼接至模板基因组的工具.它在拼接35碱基长度的序列时,可以达到每小时2.5亿次 ...

最新文章

  1. torch动态学习率代码
  2. java栈代码执行_这段实现栈的java代码执行错误..
  3. Python为何如此优秀?斯坦福教授告诉你!
  4. php mysqli不识别,不识别数据库PHP MYSQLi中的密码
  5. linux shell实现随机数多种方法(date,random,uuid)
  6. C# XML操作之读取XML数据
  7. 电脑控制Android设备的软件——Total Control
  8. AcWing(状态机模型) 1049. 大盗阿福
  9. 建模步骤_UG1847建模机械零件,零基础可读详细图文步骤
  10. air724UG + Luat玩转物联网(一) 环境搭建及固件烧录
  11. 万恶的Tomcat8.5
  12. 【实验四 循环结构】7-7 求Fibonacci(斐波那契)数列的n项和
  13. 查看win10电脑电池损耗
  14. Android很好看的登陆界面(包含详细代码)
  15. 百度云盘限速破解方式汇总
  16. 中国人民大学孟生旺教授《金融数学》资源
  17. 线上打印马上送,支持线上打印文档的软件
  18. DNS解析和DNS缓存, 如何清理DNS解析缓存
  19. 运动会管理系统JAVA SSH
  20. n个数中奇数和,偶数和

热门文章

  1. 2021高考正安二中成绩查询,2021年江西高考主要科目考试结束 6月23日公布成绩
  2. 流年,时间都去哪儿了
  3. python网页快速保存程序
  4. CoinUp罗一哲:科幻主义90后无性别者区块链金融创业者
  5. 显示杂谈(8)色域,色偏及色温
  6. 惠普计算机电脑底盖怎么打开,惠普笔记本dv4拆机图解
  7. python推箱子游戏代码_用python入门知识做推箱子游戏,若能打过第三关,则可以学会编程...
  8. Authentication 和 Authorization 的区别
  9. Python_Open3D
  10. hive 十六进制转十进制_0026-Hive使用十六进制分隔符异常分析