HeapFree
代码位置和生命及参考资料,请参考上一篇:)
HeapFree -> RtlFreeHeap
这个函数直接调用的就是RtlFrreHeap,前面依然是检查一下参数,判断一下标志位。
pInUse = (ARENA_INUSE *)ptr - 1;
if (!(subheap = HEAP_FindSubHeap( heapPtr, pInUse ))) goto error;
然后用当前INUSE的块的位置,调用HEAP_FindSubHeap函数找到当前INUSE的前面一个INUSE块的子堆的指针,并检查这个块是不是一个有效的块。
然后调用HEAP_MakeInUseBlockFree()函数,这个函数的作用是把InUse的block变为空闲的。下面我们看看这个函数:
HeapFree -> RtlFreeHeap -> HEAP_MakeInUseBlockFree
if (pArena->size & ARENA_FLAG_PREV_FREE)
首先检查要释放的空间的大小和前一块block是否也是空闲的,若前一块也是空闲的,就把前一块空闲块和这个释放的块合并起来做为一个更大的空闲块。若否,仅把当前块转为空闲块。
接着调用HEAP_CreateFreeBlock把这个原本InUse的块转换成Free的块,其实就是把结构变变,然后把标志位制为free,并且挂入空闲队列。
如 果刚才编程free的这个block是最后不是最后一个block,那么回到RtlFreeHeap继续执行,如果刚才转换成Free的block是某个 子堆的最后一个block,那就继续看看这个子堆不是第一个subheap并且是空的,那么整个subheap也一起释放掉
-
代码:
全选
-
545 if (((char *)pFree == (char *)subheap->base + subheap->headerSize) &&
546 (subheap != &subheap->heap->subheap))
547 {
548 SIZE_T size = 0;
549 void *addr = subheap->base;
550 /* Remove the free block from the list */
551 list_remove( &pFree->entry );
552 /* Remove the subheap from the list */
553 list_remove( &subheap->entry );
554 /* Free the memory */
555 subheap->magic = 0;
556 NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
557 return;
558 }
然后返回到RtlFreeHeap(),若刚才设置了share标志位,进入了临界区,则退出临界区,返回TRUE,表示释放成功。
若刚才中途出错,则 跳转到goto的位置,撤出临界区和返回错误码,并且返回 FALSE.