当前位置:C++技术网 > 资讯 > 函数内部分析:2 delete的内部执行逻辑深入分析

函数内部分析:2 delete的内部执行逻辑深入分析

更新时间:2015-06-23 19:52:50浏览次数:1+次

    delete用来释放通过new创建的内存,想必你已经十分熟悉。你也知道如何使用了。或许你并不清楚,不管如何,都有必要看看内部的实现机制,可以加深理解,让你对使用规则有一个更好的认识,而不是模糊的记忆。


    在delete的内部执行的过程大致如下:
    最先检测的是传入的唯一的一个指针参数,如果指针为空,不管delete多少次都没有关系。因为在内部首先就是判断指针是否为空,如果为空,则直接返回。
    因为new操作是在进程的堆中分配内存的,而一个进程有可能有很多的线程,而进程堆作为一个进程的多个线程的公共资源,访问时必然不能多个线程同时访问,否则会出现重复分配和释放的情况。用术语讲,进程堆就是临界资源。对临界资源的访问,每次只能允许一个访问。因此,一个线程在请求堆分配内存前,是要锁定堆,不允许其他进程操作。加入堆已经有一个线程在访问,则自己要等待。分配好内存后,就会解锁堆,让其他线程可以去分配内存。在锁定期间,线程就开始分配内存。
    同样,delete去释放堆内存,也是要锁定后才操作,操作完后解锁的。原理同new一样。
    delete在释放内存时,首先是去获得指向堆的内存起始地址的指针,然后去修改内存块的类型,将使用状态修改为未使用状态,则达到释放的效果。下次再分配堆内存时,检测到这些内存块的状态是未分配状态,则可以将其分配给其他线程使用。
    虽然delete使用起来是很方便的,但是多了解一下底层的执行过程,可以深刻的理解这个使用规则,运用起来也更加灵活自由。

    以下是跟踪到的内部实现代码,可以参考学习一下:


void operator delete(void *pUserData)//pUserData就是delete pUserData的指针
{
     _CrtMemBlockHeader * pHead;
     RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
    if (pUserData == NULL)return;//检查空指针你

    _mlock(_HEAP_LOCK);  /* 阻塞其他线程,锁定线程堆,互斥访问 */
    __TRY

    /* 获取指向内存块其实地址指针 */
    pHead = pHdr(pUserData);

    /* 验证内存块的类型,验证内存块是否有效 */
    _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

    _free_dbg( pUserData, pHead->nBlockUse );

    __FINALLY
    _munlock(_HEAP_LOCK);  /* 释放线程堆,其他线程可以访问了 */
    __END_TRY_FINALLY

    return;
}