VC-CRT调试功能

来源:互联网 发布:淘宝对纯棉全棉的定义 编辑:程序博客网 时间:2024/05/22 07:05

VC-CRT调试功能

摘自:http://blog.csdn.net/zytju1983/article/details/3466578

基于VC系列工具做开发的程序员肯定对C运行库(以下简称CRT))概念不陌生,平时编写的大部分C/C++程序都需要静态或动态链接CRT,编译器一般将CRT作为默认库链接,不需要显式设置,可能大部分人使用CRT的功能仅限于一些工具类函数的调用,像字符串类,日期时间类,文件类,输入输出类,操作系统接口包装类等,却忽略了CRT强大的调试功能,本篇想简要介绍一下CRT提供的重要调试支持,很多细节可以查阅MSDN。需要说明的是CRT的调试功能只有在调试版本可用,包含crtdbg.h头文件,工程需要至少以下两个设置:

1. 定义了预处理宏_DEBUG;

2. 动态或静态链接CRT的调试版本

CRT的调试功能大部分都在围绕调试堆作文章,也即动态内存调试诊断,其他还有一些工具宏与调试报告机制及应用钩子机制,下面具体分析之。

1. 调试报告机制

这是CRT向用户提供调试信息的方式,平时调试程序看到的弹出一个断言,错误对话框,还有运行过程中调试窗口发出的警告信息,都是CRT发出的调试报告,很多其他调试功能都利用了这一基础服务,包括内存dump展示,内存泄露报告,用户使用的_ASSERT,_ASSERTE等断言宏都调用了调试报告服务。

调试报告按照报告内容的性质分为三个类型:WARN,ASSERT,ERROR,报告有3中呈现形式:调试窗口,弹出对话框,文件(包括标准输出),默认情况下WARN类型报告输出到调试窗口,其他两个均为弹出对话框。通过以下三个函数提供相应服务:

1). _CrtSetReportMode:设置各个类型的输出方式

2). _CrtSetReportFile:设置输出的文件

3). _CrtDbgReport:输出调试报告

为方便用户使用调试报告服务,CRT定义了许多宏,包括_ASSERT,_ASSERTE,RPTx等,最常用的就是_ASSERT与_ASSERTE断言宏,利用RPTx可输出其他类型的调试报告,这些宏都调用了_CrtDbgReport(,,,),用户可在程序适当地方调用这些宏方便程序的调试。

有些用户可能不满足于以上三种报告呈现方式,希望自定义自己的报告输出方式,或想跟踪记录报告的输出等,这时可通过_CrtSetReportHook(...)设置自己的报告钩子函数,这样每当CRT需要输出调试报告时均先调用用户设置的钩子函数,如果钩子函数返回TRUE,CRT则不再进行默认处理,否则继续正常的处理流程。

2. 调试堆检查机制

这应该是CRT的核心调试功能,调试版程序通过malloc/new分配的内存均来自调试堆,C/C++程序最多的bug均是有关内存的,尤其是动态内存,包括内存泄露,堆溢出,堆破坏,自由内存再次使用等,调试堆检查机制提供了许多功能来发现运行时的内存问题。为此,CRT实现了自己的调试堆管理器来支持相应功能的实现。

调试堆管理器为每个用户分配的内存额外分配一个块头结构及相应堆溢出检测间隔内存,所以调试版本分配内存会额外分配更多的空间,块头结构记录了这块内存的相应信息(大小,类型,请求分配的文件及行号等),所有的块头结构形成一个双向链表,然后保存一个最新的链表头指针。每当用户内存分配成功后,调试堆管理器将堆溢出检测间隔内存全部置为0xFD,这样就可在适当时候检查内存是否为0xFD来判断是否发生了堆溢出。

有了调试堆管理器,就可方便提供各种内存调试功能了,CRT具体是通过如下函数来提供服务的:

1). _CrtSetDbgFlag:通过设置不同的开关可改变CRT相应行为,例如是否在每次分配或释放内存时都检查堆的完整性,是否在程序退出前报告内存泄露情况等。

2). _CrtMemCheckPoint:可获取一个当前堆的分配状态信息

3). _CrtMemDifference:可检查不同时刻堆的状态改变

4). _CrtCheckMemory:可检查堆的完整性

5). _CrtDumpMemoryLeaks:可报告内存泄露情况

6) ._CrtMemDumpAllObjectsSince:可报告某个时刻以来堆内存信息

7). _CrtSetAllocHook:设置分配钩子,可跟踪堆的每次分配或释放

8). _CrtSetBreakAlloc: 设置分配断点,可跟踪某次分配请求,调试过程中出现相应分配请求后程序将中断下来

原创粉丝点击