memwatch的使用(一)

简介:





本文转自 xkdcc 51CTO博客,原文链接:http://blog.51cto.com/brantc/116677,如需转载请自行联系原作者  linux下的测试工具真是少之又少,还不好用,最近试用了memwatch,感觉网上的介绍不太好,所以放在这里跟大家分享 。其实大部分都是看的帮助,很多地方翻译得不好还有错,请原谅指出最好看原文。如果转载或引用,请注明我的博客地址,谢谢。
       

介绍

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-landNML)内存填充。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 MemWatchI/O 操作
对于一般的操作,MemWatch创建memwatch.log文件。有时,该文件不能被创建;MemWatch会试图创建memwatNN.log文件,NN01~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 MemWatchC++的支持
    可以将MemWatch用于C++,但是不推荐这么做。请详细阅读memwatch.h中关于对C++的支持。
 

使用

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)
 
2mwTRACEmwASSERTmwVERIFYmwPuts顾名思义,就不再赘述。仅需要注意的是,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都遵照这个规则。
3ARI机制即程序设置的“Abort, Retry, Ignore选择陷阱。
mwSetAriFunc
设置“Abort, Retry, Ignore”发生时的MemWatch调用的函数.当这样设置调用的函数地址时,实际的错误消息不会打印出来,但会作为一个参数进行传递。
如果参数传递NULLARI处理函数会被再次关闭。当ARI处理函数关闭后, meewatch会自动调用有mwSetAriAction()指定的操作。
正常情况下,失败的ASSERT() or VERIFY()会中断你的程序。但这可以通过mwSetAriFunc()改变,即通过将函数"int myAriFunc(const char *)"传给它实现。你的程序必须询问用户是否中断,重试或者忽略这个陷阱。返回2用于Abort 1用于Retry,或者0对于Ignore。注意retry时,会导致表达式重新求值.
 MemWatch有个默认的ARI处理器。默认是关闭的,但你能通过调用mwDefaultAri()开启。注意这仍然会中止你的程序除非你定义MEMWATCH_STDIO允许MemWatch使用标准CI/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月前
|
运维 监控 异构计算
142_故障容错:冗余与回滚机制 - 配置多副本的独特健康检查
在大语言模型(LLM)的生产环境部署中,系统的可靠性和稳定性至关重要。随着LLM应用场景的不断扩展,从简单的文本生成到复杂的多模态交互,用户对服务可用性和响应质量的要求也日益提高。据2025年最新的AI服务可用性报告显示,顶级AI服务提供商的SLA(服务级别协议)承诺已达到99.99%,这意味着每年的计划外停机时间不得超过52.56分钟。
|
存储 编解码 缓存
webgl系列之抗锯齿和深度缓存
前言 大家好我是Fly 哥, 这是今年webgl 系列的第三篇文章, 如果你之前的两篇文章没看的话,建议先看一下,然后再来看这一篇文章 Webgl 系列之buffer的使用 webgl系列之对光栅化的理解 上一篇文章,任何虚拟3维世界的转换到二维屏幕中通过「采样」 也就判断屏幕上的每个像素中心点是不是在三角形内部的得到了 下面这幅图: 图片 走样之前 这时候有同学问, 这不像三角形哇, 这个其实用个专业的词—— 「锯齿」 , 我的理解 一个三角形经过光栅化后, 得到屏幕上每一个像素点 组成的像素点的集合。那到底是经过什么样的处理得到下面这张图: 图片 final 反走样 其实出现上面
webgl系列之抗锯齿和深度缓存
|
6月前
|
机器学习/深度学习 自然语言处理 监控
ms-swift 部分命令行参数说明
本资源介绍了机器学习训练中的关键参数设置及其影响,包括训练轮数、批量大小、学习率、梯度累积、模型微调等,并提供了针对不同任务和硬件配置的推荐值,帮助提升模型训练效率与性能。
737 4
|
7月前
|
安全 算法 数据安全/隐私保护
远控安全进阶之战:TeamViewer/ToDesk/向日葵设备安全策略对比
在数字化时代,卓越的远程控制软件需兼顾功能与体验,包括流畅连接、高清画质、低门槛UI设计、毫秒级延迟及多功能性,同时要有独树一帜的远控安全技术,通过前瞻性安全策略阻挡网络风险,为用户打造全方位安全体验,在基础安全防护上不断创新。本文选取了当下热门的TeamViewer、ToDesk、向日葵三款远程控制软件,从软件介绍、远控安全策略等多个维度进行深入对比,以呈现一场精彩的远控软件安全进阶“大比拼”。
759 13
|
网络协议 网络架构
OSPF中的External LSA详解
OSPF中的External LSA详解
542 4
|
消息中间件 存储 网络协议
操作系统的心脏:深入理解进程间通信(IPC)机制
在现代计算机系统中,操作系统扮演着至关重要的角色,而进程间通信(IPC)作为操作系统的核心功能之一,极大地影响着系统的性能和稳定性。本文将通过浅显易懂的语言,详细探讨进程间通信的基本原理、主要类型及其实际应用,旨在为读者提供一个清晰且全面的理解和认识。 ##
847 1
|
存储 数据采集 监控
CDGA\如何建立实现数据治理的效率价值框架:实践案例解析
数据治理是一个持续优化的过程。组织应建立健全的监督与评估机制,定期对数据治理工作进行评估,发现问题及时整改。广东药科大学通过数据全景图和数据监控大屏,实现了对数据治理成果的动态、多维度呈现与监控,为科学管理决策提供了有力支撑。
|
芯片
关于LDO,读懂这一篇就够了
**LDO(低压差线性稳压器)简述** LDO用于转换不同直流电压,常见于电子设备,因其低成本、高性能和易用性。它通过内部反馈控制功率晶体管来稳定输出电压,消耗部分功率以保持输出稳定。关键参数包括输入电压范围、静态功耗、电源纹波抑制比(PSRR)、输出电流和电压精度。LDO特点包括自放电功能(快速放电输出电容)和软启动(平滑输出电压上升)。设计时需考虑效率、动态负载调整、瞬态响应和压差。布局上,输入输出电容靠近LDO并良好接地以优化性能。
382 15
|
缓存 算法 安全
深入理解操作系统:虚拟内存管理的原理与实践
【4月更文挑战第8天】 在现代计算机系统的设计与实现中,虚拟内存管理是操作系统核心功能之一。通过抽象物理硬件的细节,提供给用户一个看似无限的地址空间,它允许多个进程独立运行,同时为系统提供必要的内存保护机制。本文将探讨虚拟内存的基本原理、关键组件以及它在操作系统中的实际应用,旨在为读者提供一个清晰的视角来理解这一复杂的技术概念,并讨论其对现代计算环境的重要性和影响。
429 0
|
算法 搜索推荐 关系型数据库
Elasticsearch算分优化方案之rescore_query
Elasticsearch算分优化方案之rescore_query
314 0