上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
6.4.2 堆的销毁
堆的销毁分两种情况:一种情况是销毁单个堆;另外一种情况是销毁当前线程的所有堆。其中,第二种情况一般在线程结束的时候,由线程结束收尾函数(KernelThread Wrapper函数)调用,用来释放当前线程尚未释放的所有堆对象。对于第一种情况,一般是由应用程序编写者调用的,用来撤销自己创建的堆。
其中,销毁当前线程所有堆(DestroyAllHeap)的实现,也是调用了销毁单个堆的实现算法,因此,在此只简单介绍销毁单个堆的实现代码。对于堆的撤销操作,比较简单,所需要完成的,只是内存资源的回收而已。目前的实现中,在DestroyHeap的实现中,完成下列动作:
① 从当前线程的堆链表中,删除要销毁的堆对象(该对象作为函数的参数传递);
② 释放该堆对象申请的所有虚拟区域;
③ 然后把虚拟区域链表所占用内存释放,即虚拟区域节点占用内存;
④ 最后,释放堆对象本身。
代码如下。
static VOID DestroyHeap(__HEAP_OBJECT* lpHeapObject) { __VIRTUAL_AREA_NODE* lpVirtualArea=NULL; __VIRTUAL_AREA_NODE* lpVirtualTmp =NULL; LPVOID lpVirtualAddr=NULL; DWORD dwFlags =0L; if(NULL==lpHeapObject) //Parameter check. return; if(lpHeapObject==lpHeapObject->lpNext) //Only one heap object //in current thread. { __ENTER_CRITICAL_SECTION(NULL,dwFlags); lpHeapObject->lpKernelThread->lpHeapObject=NULL; __LEAVE_CRITICAL_SECTION(NULL,dwFlags); } else //Delete itself from the kernel thread's heap list. { __ENTER_CRITICAL_SECTION(NULL,dwFlags); if(lpHeapObject->lpKernelThread->lpHeapObject==lpHeap Object) { lpHeapObject->lpKernelThread->lpHeapObject=(LPVOID) lpHeap Object->lpNext; } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); lpHeapObject->lpPrev->lpNext=lpHeapObject->lpNext; lpHeapObject->lpNext->lpPrev=lpHeapObject->lpPrev; } lpVirtualArea=lpHeapObject->lpVirtualArea; while(lpVirtualArea) { lpVirtualTmp=lpVirtualArea; lpVirtualArea=lpVirtualArea->lpNext; RELEASE_VIRTUAL_AREA(lpVirtualTmp->lpStartAddress); //Release the virtual area. RELEASE_KERNEL_MEMORY((LPVOID)lpVirtualTmp); } // //Now,should release the heap object itself. // RELEASE_KERNEL_MEMORY((LPVOID)lpHeapObject); return; }