快速业务通道

C++编码中减少内存缺陷的方法和工具

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29
数IsBadReadPtr、IsBadWritePtr、IsBadStringPtr、IsBadCodePtr用来检测指针指向的内存区域是否可读/写。C运行时库提供了_CrtIs ValidPointer、_CrtIsValidHeapPointer等函数,MFC库提供了AfxIsValidAddress、AfxIsValidString函数来完成类似功能。

(2)对基于MFC的程序,ASSERT_VALID宏通过调用重载的AssertValid函数来确定指向CObject派生类对象的指针是否有效。ASSERT_VALID宏主要调用了AfxIsValidAddress函数和CObject派生类对象的AssertValid函数(参考MFC源代码afx.h、objcore.cpp)。

2.2 利用C运行时刻库检查内存泄漏

VC++的C运行库(CRT)提供了广泛的功能,帮助用户检测内存泄漏。CRT提供了_CrtMemCheckPoint、_CrtDump MemoryLeaks、_CrtSetDbgFlag等函数来帮助调试内存泄漏。

对于非MFC的工程, 要开启有效的内存泄漏报告功能, 需要进行如下设置:

(1)在StdAfx.h的头部添加如下代码并开启编译器/Yu 选项:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, THIS_FILE, __LINE__)

(2)确保在每个.cpp文件的头部包含以下内容:

#include "stdafx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

(3)在程序的开始处开启报告内存泄漏的开关:

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);

对于MFC工程, MFC已经做了相关的工作, 只需要确认在每个.cpp文件的头部包含上述第(2)点的内容。

在某些情况下,需要知道发生内存泄漏的内存块中的内容,但是标准的内存转储只是内存块头部的十六进制形式。为了得到更多的有用信息,需要以用户块类型(_CLIENT_ BLOCK)申请内存,并利用_CrtSetDumpClient建立用户块型内存的转储函数。具体的说,对于不是从CObject继承的类,需要:

(1)为每个类/结构指定一个用户块子类型(参考crtdbg.h)。

(2)在申请内存时,采用重载的new形式:void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine)(参考MFC源代码 afxmem.cpp),其中nType就是用户块的子类型。

(3)创建一个用户块内存转储函数,专门对每种需要转储的子类型进行处理(需要包含dbgint.h)。

(4)利用_CrtSetDumpClient对用户块内存转储函数进行注册(参考MFC源代码dumpinit.cpp)。

对于从CObject继承来的类,MFC 已经按照上述方法做了基础工作(参考MFC源代码 afxmem.cpp、dumpinit.cpp)。要有效转储从CObject继承的对象,需要:(1)对每个从CObject继承的类重载虚函数Dump。(2)在程序的初始化部分 加入代码 afxDump.SetDepth(1)来开启深度转储。

2.3 利用Purify和Insure++查找运行时内存缺陷

Rational Purify和Parasoft Insure++ 是用于运行时错误检查的工具。Purify主要检测:数组内存越界读/写,使用未初始化的内存,对已释放的内存进行读/写,内存泄漏等。Insure++利用其专利技术(源码插装和运行时指针跟踪)能够发现大量的内存操作错误,报告错误的源代码行和执行轨迹。根据笔者的测试(基于98个有各种内存错误的C++程序,涵盖了典型情形),Insure++ 6.1都能准确检测。

3 利用VC++环境的调试和诊断功能,检查和发现常见内存缺陷

理解常见的内存缺陷问题以及在VC++环境下的症状,能辅助我们减少问题的发生和及时修改问题。

从错误的表现形式上看, 和堆栈有关的错误主要分为两大类:堆栈溢出和函数返回信息被破坏。

(1)堆栈溢出(overflow)

此类错误主要有两种情形:

1)过大的局部变量。缺省情况下Windows为每个线程保留1M堆栈空间。在菜单Project->Properties->Configuration Properties -> Linker->System中可以看到

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号