一个C++的内存池和内存管理的实现(八)

上一章那东西怎么用?很简单。比如:

SmartHeapMemPtr<int> p = NEW int[100];
for (int i = 0; i <= 100; i ++)
    p[i] = 0;  // 前100次正常,到最后一个循环时抛出异常

你可以给SmartHeapMemPtr类里的那4个指针内容访问函数里的抛出异常的语句打上断点。这样一旦走到断点,就表明有越界了,此时查看call stack,就可以找到代码问题所在。

越界抛出异常是怎么办到的?SmartHeapMemPtr<int> p = NEW int[100];这个语句在执行时,会调用SmartHeapMemPtr::operatore=函数,就是下面这个

SmartHeapMemPtr& operator=(const T* p) 
{
    ...
            m_pData->m_pEndMemPtr = m_pData->m_pStartMemPtr + pPrefix->d.pPostfix->nActualSize - 1;
    ...
}

这样分配给p的内存块的范围它就获得了。接下来每次循环访问p[i]时,会调用inline T& operator [](const int n),里面做了个当前指针访问地址是否超出了范围的判断。

那么如果我bug都检查完了,该发布release版的时候,该怎么关掉越界检查?我们下面定义一个宏

#ifdef USE_SMART_HEAP
    #define HEAP_MEM_PTR(a) VFC::SmartHeapMemPtr<a>
#else
    #define HEAP_MEM_PTR(a) a*
#endif

然后最上面的那个测试程序的变量申明和分配就可以改成

HEAP_MEM_PTR(int) p = NEW int[100];

定义了USE_SMART_HEAP时,p就是个智能指针,未定义时就是个普通指针。我们再结合内存池,做以下宏定义

#if defined USE_SMART_HEAP
    #ifndef USE_MEM_POOL
        #define USE_MEM_POOL
    #endif
    #define HEAP_MEM_PTR(a) VFC::SmartHeapMemPtr<a>
#else
    #define HEAP_MEM_PTR(a) a*
#endif

#if defined USE_MEM_POOL
    #define NEW new(__LINE__, FILE_NAME)
    #define DEL_PTR(p) { DestructPtr(p); }
    #define DEL_ARRAY(p) { DestructArray(p); }
#else
    #define NEW new
    #define DEL_PTR(p) delete p;
    #define DEL_ARRAY(p) delete[] p;
#endif

所有指针或数组都采用NEWDEL_PTR、和DEL_ARRAY进行分配和释放操作。这里提供了三种选择。当既不做泄露和越界检查(不定义USE_SMART_HEAP)也不用内存池(也不定义USE_MEM_POOL)时,这三个宏分别对应C++内置的分配释放操作。第二种选择是采用内存池但不做泄露和越界检查(定义USE_MEM_POOL但不定义USE_SMART_HEAP)。第三种选择是既采用内存池也做泄露和越界检查(定义USE_SMART_HEAP)。这里注意,做泄露和越界检查必须采用内存池,因为越界检查里的内存块范围需要通过MemPool里定义的内存块的前缀来获得(至于泄露检查就不用说了)。

哦,还漏了DEL_PTR(p)、和DEL_ARRAY(p)对于pSmartHeapMemPtr的情况。加上

template<typename T> inline void DestructPtr(VFC::SmartHeapMemPtr<T>& p) {
    p.DecRef(); p.Release();
}

template<typename T> inline void DestructArray(VFC::SmartHeapMemPtr<T>& p) {
    p.DecRef(); p.Release();
}

好了,我们重新写一下本章开头的测试程序。应该这样写

HEAP_MEM_PTR<int> p = NEW int[100];
for (int i = 0; i <= 100; i ++)
    p[i] = 0;  // 前100次正常,到最后一个循环时抛出异常
DEL_ARRAY(p);

只要程序里所有的指针相关内容都这么写,就可以做到泄露和越界的自动检查了。当然,要开了USE_SMART_HEAP宏。

可是,事情没那么简单,下章再说。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值