C++ 巧用对象辅助资源释放

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++的这个“甜头”了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注