上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
6.4.5 malloc函数和free函数的实现
malloc函数和free函数是标准C运行期库函数,实现这两个函数对于代码的移植十分有意义。很明显,采用HeapAlloc和HeapFree函数可以很容易地模拟这两个函数,但HeapAlloc函数和HeapFree函数都接受一个堆对象指针作为参数,而malloc函数和free函数则没有。因此,为了屏蔽这个差异,我们在核心线程对象(__KERNEL_THREAD_OBJECT)中引入一个默认堆的变量,所有malloc函数和free函数的内存申请都从默认堆中进行。
下面是malloc函数的实现代码。
LPVOID malloc(DWORD dwSize) { DWORD dwFlags =NULL; LPVOID lpResult =NULL; __HEAP_OBJECT* lpHeapObj=NULL; DWORD dwHeapSize=0L; if(0==dwSize) //Invalid parameter. return lpResult; if(NULL==CURRENT_KERNEL_THREAD->lpDefaultHeap) //Should create one. { dwHeapSize=(dwSize+sizeof(__FREE_BLOCK_HEADER) > DEFAULT_ VIRTUAL_AREA_SIZE) ? (dwSize+sizeof(__FREE_BLOCK_HEADER)) : DEFAULT_VIRTUAL_ AREA_SIZE; lpHeapObj=CreateHeap(dwHeapSize); if(NULL==lpHeapObj) //Can not create heap object. return lpResult; //__ENTER_CRITICAL_SECTION(NULL,dwFlags); CURRENT_KERNEL_THREAD->lpDefaultHeap=(LPVOID)lpHeapObj; //__LEAVE_CRITICAL_SECTION(NULL,dwFlags); } else { lpHeapObj=(__HEAP_OBJECT*)CURRENT_KERNEL_THREAD->lpDefaultHeap; } return HeapAlloc(lpHeapObj,dwSize); }
首先,该函授判断当前线程的默认堆对象(lpDefaultHeap)是否存在,若存在(不为NULL),则直接以默认堆为目标堆,调用HeapAlloc函数把该函数的结果返回给用户,否则,该函数首先调用CreateHeap函数创建一个默认堆,并初始化当前线程的lpDefaultHeap变量,在此基础上,再调用HeapAlloc函数。
很明显,只有malloc函数第一次调用的时候才可能会发生lpDefaultHeap为NULL的情况,后续调用的时候,不会出现这种情况。
对于free函数,实现起来就更简单了。
VOID free(LPVOID lpMemory) { __HEAP_OBJECT* lpHeapObj=NULL; if(NULL==lpMemory) return; lpHeapObj=(__HEAP_OBJECT*)CURRENT_KERNEL_THREAD->lpDefaultHeap; if(NULL==lpHeapObj) //Invalid case. return; HeapFree(lpMemory,lpHeapObj); }
首先,该函数确保当前线程的默认堆是存在的,然后调用HeapFree函数来释放具体的内存。否则可能是一种不正常操作,直接导致free函数返回。