码迷,mamicode.com
首页 > 其他好文 > 详细

boost::checked_delete

时间:2015-01-21 15:16:22      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:boost   c++   

先看一段能够正常执行的代码,但会造成内存泄漏:

deleteObject.h 

实现删除一个CObjectItem的派生类的指针所指的内存

#pragma once

namespace smtlCheck
{
	class CObjectItem;

	class CDeleteObject
	{
	public:
		CDeleteObject(void);
		~CDeleteObject(void);

		void deleteObject(CObjectItem *vObj);
	};
}
deleteObject.cpp

#include "deleteObject.h"

using namespace smtlCheck;

CDeleteObject::CDeleteObject(void)
{
}

CDeleteObject::~CDeleteObject(void)
{
}

void CDeleteObject::deleteObject(CObjectItem *vObj)
{
	<span style="color:#ff0000;">delete vObj;</span>
}
object.h

基类

#pragma once
#include <iostream>

namespace smtlCheck
{
	class CObjectItem
	{
	public:
		CObjectItem() {}
		virtual ~CObjectItem()
		{
			//print();
		}

	private:
		virtual void print() const = 0;//just for testing whether the deconstruction is called
	};
}
DivObject.h

派生类

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include "object.h"

namespace smtlCheck
{
	class CDivObject : public CObjectItem
	{
	public:
		CDivObject() 
		{
			m_pSig    = new std::string("");
			m_pIntSet = new std::vector<int>[10];
		}

		virtual ~CDivObject() 
		{
			delete m_pSig;
			delete [] m_pIntSet;
			<span style="color:#ff0000;">print();</span>
		}

		//other members...

	private:
		std::string      *m_pSig;
		std::vector<int> *m_pIntSet;

		virtual void print() const
		{
			std::cout << "the deconstruction of CDivObject is called" << std::endl;
		}
	};
}
main.cpp

#include "deleteObject.h"
#include "DivObject.h"

int main()
{

	CObjectItem *pDidObj = new CDivObject;

	//do something...

	CDeleteObject DeObj;
	<span style="color:#ff0000;">DeObj.deleteObject(pDidObj);</span>

	return 0;
}
运行程序会发现CDivObject的析构函数并没有调用。这时什么原因呢?

主要原因是在deleteObject.cpp这个文件里面,class CObjectItem这个类定义不完整,所以下面的代码:

void CDeleteObject::deleteObject(CObjectItem *vObj)
{
	<span style="color:#ff0000;">delete vObj;</span>
}
之中delete删除一个不完整定义类的指针,解决方法:

deleteObject.cpp中加上COjectItem的头文件。但这不是一个通用的解决方法,因为这种错误很难被发现,至少是编译通过(C++中,delete一个类型不完整的类对象的指针,编译器会发出警告,不幸的是,程序员有时候会忽略这种警告),最坑人的是居然能够运行,这样的错误查找起来实在是很困难。

有没有在编译器就能够找出delete一个不完整定义的指针呢?boost就提供了一个这种功能:

boost::checkde_delete可以在编译时期发现这种错误。

修改代码如下:

void CDeleteObject::deleteObject(CObjectItem *vObj)
{
	boost::checked_delete(vObj);
}
加上头文件boost/checked_delete.hpp

这样我们在编译时会发现如下错误:

 error C2027: use of undefined type ‘smtlCheck::CObjectItem‘

告诉我们CObjectItem类没有定义,在deleteObject.cpp的头文件中加上object.h,这样就解决问题了。


checked_delete的实现

template<class T> inline void checked_delete(T * x)
{
    // intentionally complex - simplification causes regressions
    typedef char type_must_be_complete[ <span style="color:#ff0000;">sizeof(T)</span>? 1: -1 ];
    (void) sizeof(type_must_be_complete);
    delete x;
}
主要利用sizeof(T),sizeof在编译时期要知道T的大小,如果T不是一个完整的定义就会在编译是报错。

这样就可以避免delete一个不完整类型的指针。


sizeof(T)返回0的情况在有些编译器上会出现:如gcc int a[0];sizeof(a)就返回0 vs上则报错。







boost::checked_delete

标签:boost   c++   

原文地址:http://blog.csdn.net/xiaoliangsky/article/details/42967823

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!