C++ 巧用对象辅助资源释放
本文是对之前一篇文章《C++ 巧用对象辅助内存回收》的扩充,内存回收篇,有网友指出使用std::unique_ptr可以来实现。其实简单的封装个内存助手,也就不想引入std呢。那篇文章是讲辅助内存回收,如果懂得举一反三的读者,就没有必要读这篇文章了。
本文简述的是如何利用对象的析构被回收特点,辅助资源回收。
开发时候,可能碰到如下的业务需求,在进入某个代码块时候,要获取资源,而退出该代码时候,需要释放资源,代码逻辑大概如下:
void func()
{
// 进入函数时候需要获取或者创建某些资源
create or lock resource
// 这里还有很多代码
// 离开函数时候需要释放该资源
release resource
}
上述的资源获取,可能是申请一块内存(这就是辅助内存回收篇的主要内容了),或者是多线程的情况下锁定某个资源,或者是创建临时目录,或者是在忙状态设置下鼠标样式为转圈(wait)样式……而在函数退出前需要对资源进行释放掉,若是内存申请则释放掉内存,若是锁定的则需要解锁,若是创建的临时目录则需要删除临时目录,若是改变鼠标样式的需要还原……
如果上面代码的出口有很多,多个return,那么就需要在每个return 前进行资源释放了。代码长时间的迭代维护修改容易漏掉对资源进行释放。这里的资源泄漏,如果是内存泄漏,可能使得程序慢慢把内存耗尽;如果是临时文件一直没有清理,会可能耗尽硬盘;如果是多线程临界区锁没释放,就是死锁问题了。这类型问题可大可小。
C++ 的对象创建时候,必然进入其构造函数,而对象被回收时候,必然进入析构函数。C++ 函数内部的局部对象,函数执行完毕,局部对象会被回收掉。基于语言这个特征,就可以封装一个辅助对象,在构造函数内锁定资源,析构函数函数内进行资源释放,这个辅助类对象在代码块内使用,辅助资源管理,这样就能优雅的做到资源回收了。
辅助类设计如下:
class CHelper
{
public:
CHelper(param)
{
// 获取自己需求的资源
// 比如申请内存、锁定临界区、创建临时目录等等
}
virtual ~CHelper()
{
// 释放资源
// 主要是构造函数的取反操作
}
};
在辅助类的帮助下,不用在每个return 返回处都写个资源回收代码,也不用担心容易漏掉某个return而导致资源泄漏了。原来的资源处理的代码逻辑就会变的简单清晰而好维护了。
做个多线程下,辅助锁定资源的例子,注意,文章目的在于介绍下面的CLocalLock:
// 锁资源的封装
class CLock
{
public:
CLock()
{
::InitializeCriticalSection(&m_crit);
};
~CLock()
{
::DeleteCriticalSection(&m_crit);
};
void Lock()
{
::EnterCriticalSection(&m_crit);
};
void Unlock()
{
::LeaveCriticalSection(&m_crit);
};
private:
CRITICAL_SECTION m_crit;
};
// 局部锁的封装,重点是这个类
class CLocalLock
{
public:
CLocalLock(CLock *pLock)
{
m_pLock = pLock;
if (m_pLock)
{
m_pLock->Lock();
}
};
~CLocalLock()
{
if (m_pLock)
{
m_pLock->Unlock();
}
};
private:
CLock * m_pLock;
};
// 在某线程函数使用上,比如一个圈子的锁来锁定某个代码段
CLock g_lock;
DWORD threadFunc()
{
CLocalLock(&g_lock);
// 这里使用g_lock,给多线程函数上锁,局部变量析构时候,会自动对g_lock进行解锁了,
// 如果函数内有多个return,也不用担心遗忘解锁自己问题
}
这是C++语言才有的特征,Java 虽然不用关心内存回收问题,但是还是要关注资源回收的,但Java 对其资源回收问题的处理就没有C++的这个“甜头”了。
(全文完)
(欢迎转载本站文章,但请注明作者和出处 云域 – Yuccn )