[C/C++]_[中级]_[使用智能指针的模式释放malloc出来的堆空间]

[C/C++]_[中级]_[使用智能指针的方式释放malloc出来的堆空间]


场景:

1. 使用auto_ptr 的方式可以wrap类对象,  之后在方法结束后可以自动释放对象, 参考;这样在有条件判断的语句时可以省掉free语句或CloseHandle.

http://blog.csdn.net/infoworld/article/details/9008911

2.C++的特性之一就是类对象(非返回值的对象)在方法结束后会自动调用析构函数,这样在析构函数里可以放一些释放资源的操作.

3. 这里实现了一个类似auto_ptr的类的实用Wrap类,可以参考根据自己需要自定义特定的Wrap类.auto_ptr的坏处之一就是只支持new出来的对象,

之二是不能删除数组. delete []

4. 恰当使用WrapObject能有效的减少内存泄漏,因为在很多C编程里, 太多的if语句在return前需要释放对象,很容易就会出错或多次释放。


文件 wrap_object.h

#ifndef __WRAP_OBJECT
#define __WRAP_OBJECT

#include <stdlib.h>
#include <Windows.h>


template<BOOL (WINAPI* WrapHandleFunc)(void*)>
class WrapHandle
{
public:
	WrapHandle(void* data):data_(data){}
	~WrapHandle()
	{
		if(data_)
		{
			WrapHandleFunc(data_);
			data_ = NULL;
		}
	}
private:
	void* data_;
};

class WrapMalloc
{
public:
	WrapMalloc(void* data):data_(data){}

	~WrapMalloc()
	{ 
		free(data_);
		data_ = NULL;
	}
	void Reset()
	{
		free(data_);
		data_ = NULL;
	}
private:
	void* data_;
};

#endif

使用方式:

// Specify an HTTP server.
  const char* www = "www";
  std::string URLADDR = DhOptionDomain::GetValue("url:brand");
  const char* www_start = strstr(URLADDR.c_str(),www);
  

  if( !hSession )
  {
	  return kNetworkError;
  }
  WrapHandle<WinHttpCloseHandle> session_wh(hSession);
  
  wchar_t* www_start_unicode = ConvertUtf8ToUnicode(www_start);
  WrapMalloc www_wm(www_start_unicode);
  hConnect = WinHttpConnect( hSession, www_start_unicode,  
                               INTERNET_DEFAULT_HTTP_PORT, 0 ); 

  // Create an HTTP request handle.  
  if(!hConnect )  
  {
	 return kNetworkError;  
  }
  WrapHandle<WinHttpCloseHandle> connect_wh(hConnect);

  hRequest = WinHttpOpenRequest( hConnect, L"GET", L"/win-update.xml",  
                                   NULL, WINHTTP_NO_REFERER,   
                                   WINHTTP_DEFAULT_ACCEPT_TYPES,   
                                   WINHTTP_FLAG_REFRESH ); 
  // Send a request.  
  if(!hRequest)
  {
	 return kNetworkError;
  } 

  WrapHandle<WinHttpCloseHandle> request_wh(hRequest);

  bResults = WinHttpSendRequest( hRequest,  
                                   WINHTTP_NO_ADDITIONAL_HEADERS, 0,  
                                   WINHTTP_NO_REQUEST_DATA, 0,   
                                   0, 0 );
  
  // End the request.  
  if(!bResults )
  {
	return kNetworkError;
  } 
  bResults = WinHttpReceiveResponse( hRequest, NULL );  

注意: 如果没有WrapObject的话你就得记得在if里释放不断增加的 Handle对象,它是提高程序质量的好处之一,建议直接用到项目里.