📄 klheap.c
字号:
// 减去已分配的内存大小
lpHeap->lpbCur += dwCommitSize;
lpHeap->dwCurUseSize += dwCommitSize;
lpHeap->dwTotalCommitSize += dwCommitSize;
*lpdwRealSize = dwCommitSize - uiNewSectionSize;
//RETAILMSG( 1, ( "GetSystemMem:*lpdwRealSize=%d,dwSize=%d,p=0x%x,lpHeap->lpbCur=%x, ProcID=%x, ThreadID=%x, CPSR=%x.\r\n",*lpdwRealSize, dwSize, p, lpHeap->lpbCur, KL_GetCurrentProcessId(), KL_GetCurrentThreadId(), KL_GetCPSR() ) );
}
else
{
WARNMSG( DEBUG_GETSYSTEMMEM, ( "error: GetSystemMem: can't to commit enough memory size(%d).\r\n", dwCommitSize ) );
}
}
DEBUGMSG( DEBUG_GETSYSTEMMEM, ( "GetSystemMem:lpHeap=%x,dwTotalSize=%d,ProcessId=%d.\r\n", lpHeap, lpHeap->dwTotalCommitSize, KL_GetCurrentProcessId() ) );
return p;
}
//#else
else
#endif
{ // 用DoAllocPageMem去分配内存
LPBYTE p = NULL;
*lpdwRealSize = 0;
dwSize += sizeof(SECTION); // 真实的需要分配的内存大小
p = DoAllocPageMem( dwSize, lpdwRealSize, 0 );
if( p )
{ // 将其加入堆链表
Heap_AddToSection( lpHeap, (LPSECTION)p, *lpdwRealSize );
lpHeap->dwTotalReserveSize += *lpdwRealSize;
lpHeap->dwTotalCommitSize += *lpdwRealSize;
p = p + sizeof(SECTION);
*lpdwRealSize -= sizeof(SECTION);
}
return p;
}
}
/**************************************************
声明:static BOOL Heap_MemCheck( LPHEAP lpHeap )
参数:
lpHeap - HEAP 结构指针,指向堆信息
返回值:
假如成功,返回TRUE; 否则,返回FALSE
功能描述:
检查堆是否合法
引用:
************************************************/
static BOOL Heap_MemCheck( LPHEAP lpHeap )
{
LPBLOCK lpBlock, lpFirstBlock;
// 进入互斥段
EnterCriticalLock( lpHeap, TRUE );
lpFirstBlock = lpBlock = lpHeap->lpFirstBlock;
KL_DebugOutString( "........check heap.........\r\n" );
while( lpBlock )
{
if( IS_ALLOC(lpBlock) )//&& !IS_GAP( lpBlock ) )
{
ASSERT_NOTIFY( 0 , (char*)lpBlock + sizeof( BUSY ) );//"memory not free when exit ap!!" );
}
lpBlock = lpBlock->busy.lpNext;// - (ALLOC_FLAG+BUSY_FLAG);
lpBlock = (LPBLOCK) ( (DWORD)lpBlock & ( ~(ALLOC_FLAG+BUSY_FLAG) ) );
}
// 离开互斥段
LeaveCriticalLock( lpHeap, TRUE );
return TRUE;
}
/**************************************************
声明:BOOL WINAPI KL_HeapDestroy( HANDLE hHeap )
参数:
hHeap - 堆句柄(为之前调用KL_HeapCreate所返回的句柄)
返回值:
假如成功,返回TRUE; 否则,返回FALSE
功能描述:
破坏堆
引用:
************************************************/
BOOL WINAPI KL_HeapDestroy( HANDLE hHeap )
{
LPHEAP lpHeap = (LPHEAP)hHeap;
#ifdef VIRTUAL_MEM
// 如果系统有MMU管理,则用该段代码
if( lpHeap->dwOption & HEAP_VIRTUAL_ALLOC )
{ // // 用VirtualFree去释放内存
LPSECTION lps, lpNext;
// 进入互斥段
EnterCriticalLock( lpHeap, TRUE );//LN:2003-05-13, Add
RETAILMSG( 1, ( "Heap_Release:lpHeap=%x.lpbBase=%x.\r\n", lpHeap, lpHeap->lpbCurReserveBase ) );
// 释放所有的内存段
lps = lpHeap->lpSection;
while( lps )
{
lpNext = lps->lpNext;
KL_VirtualFree( lps, 0, MEM_RELEASE );
lps = lpNext;
}
// 离开互斥段
LeaveCriticalLock( lpHeap, TRUE );//LN:2003-05-13, Add
return DoHeapDestroy( lpHeap );
}
else
#endif
{ // 用DoFreePageMem去释放内存
LPSECTION lps, lpNext;
// 进入互斥段
EnterCriticalLock( lpHeap, TRUE );
// 释放所有的内存段
lps = lpHeap->lpSection;
while( lps )
{
lpNext = lps->lpNext;
DoFreePageMem( lps, lps->ulLen );
lps = lpNext;
}
// 离开互斥段
LeaveCriticalLock( lpHeap, TRUE );
return DoHeapDestroy( lpHeap );
}
}
/**************************************************
声明:void _InsertToFree( LPHEAP lpHeap, LPBLOCK p )
参数:
lpHeap - HEAP结构指针
p - 内存块
返回值:
无
功能描述:
将一个内存块插入堆空闲链表,以便以后使用
引用:
************************************************/
static void _InsertToFree( LPHEAP lpHeap, LPBLOCK p )
{
p->lpPrevFree = 0;
if ( (p->lpNextFree = lpHeap->lpFreeList) != 0 )
lpHeap->lpFreeList->lpPrevFree = p;
lpHeap->lpFreeList = p;
}
/**************************************************
声明:void _RemoveFromFree( LPHEAP lpHeap, LPBLOCK p )
参数:
lpHeap - HEAP结构指针
p - 内存块
返回值:
无
功能描述:
将一个内存块移出堆空闲链表,以便使用
引用:
************************************************/
static void _RemoveFromFree( LPHEAP lpHeap, LPBLOCK p )
{
LPBLOCK f, b;
f = p->lpNextFree;
b = p->lpPrevFree;
if ( b )
b->lpNextFree = f;
else
lpHeap->lpFreeList = f;
if ( f )
f->lpPrevFree = b;
}
/**************************************************
声明:void * WINAPI KL_HeapAlloc( HANDLE hHeap, DWORD dwFlags, DWORD dwSizeNeeded )
参数:
hHeap - 堆句柄
dwFlags - 功能,可以为以下值:
HEAP_NO_SERIALIZE - 不需要串行化(互斥操作)
dwSizeNeeded - 需要分配的内存大小
返回值:
假如成功,返回非NULL的指针; 否则返回NULL
功能描述:
从堆里分配一个内存快
引用:
系统API
************************************************/
#define DEBUG_HEAPALLOC 0
void * WINAPI KL_HeapAlloc( HANDLE hHeap, DWORD dwFlags, DWORD dwSizeNeeded )
{
LPBLOCK p, x, lpBigBlock;
DWORD dwBigSize, dwSize;
DWORD dwRealSize;
LPHEAP lpHeap = (LPHEAP)hHeap;
DWORD dwSave = dwSizeNeeded;
if ( !dwSizeNeeded )
goto M_RETNULL;
// 对齐大小
dwSizeNeeded = ((dwSizeNeeded + ALIGNMASK) & ~ALIGNMASK) + sizeof(BUSY);
if ( dwSizeNeeded < sizeof(BLOCK) )
dwSizeNeeded = sizeof(BLOCK);
lpBigBlock = 0; // 用于记录 > dwSize 的最小的一个空闲快
dwBigSize = 0; // 用于记录 lpBigBlock的大小
//进入互斥段
EnterCriticalLock( lpHeap, TRUE );//LN:2003-05-13, Add
DEBUGMSG( DEBUG_HEAPALLOC, ( "+++M(0x%x,lock=%d,dwOption=0x%x)M+++.\r\n", KL_GetCurrentThreadId(), lpHeap->iLockCount, lpHeap->dwOption ) );
// 查找堆空闲链表-在所有大于dwSizeNeeded的空闲块里得到一块适当的空闲块
for ( p = lpHeap->lpFreeList; p; p = p->lpNextFree )
{
if ( (dwSize = (char*)p->busy.lpNext - (char*)p) >= dwSizeNeeded )
{ // 空闲块的尺寸大于需要的尺寸
if ( dwSize < dwSizeNeeded + dwSizeNeeded )
{ // 假如该空闲块的尺寸小于需要的尺寸的两倍,符合要求,退出查找
break;
}
// 空闲块的尺寸太大,如果符合条件(是目前得到的空闲块里最小的一块)
// 将其保存在 lpBigBlock, dwBigSize里
if ( !lpBigBlock || dwSize < dwBigSize )
{
lpBigBlock = p;
dwBigSize = dwSize;
}
}
}
// 是否已经得到符合条件的空闲块
if ( p == NULL && (p = lpBigBlock) == NULL )
{ //没有,需要从系统空闲内存去分配大的内存,dwRealSize用于保存实际得到的内存块大小
p = GetSystemMem( lpHeap, dwSizeNeeded+sizeof(BUSY), (DWORD*)&dwRealSize );
if ( p == NULL )
{ // 无法从系统分配内存,退出
DEBUGMSG( DEBUG_HEAPALLOC, ( "---M(0x%x)M---.\r\n", KL_GetCurrentThreadId() ) );
LeaveCriticalLock( lpHeap, TRUE );
goto M_RETNULL;
}
ASSERT( dwRealSize >= dwSizeNeeded+sizeof(BUSY) );
dwRealSize &= ~ALIGNMASK;
if ( lpHeap->lpLastBlock &&
(char*)p == ((char*)lpHeap->lpLastBlock + sizeof(BUSY)) )
{ // 新的内存段与之前所分配的内存段是连续的,我们将其组合为一个大段
p = lpHeap->lpLastBlock;
dwRealSize += sizeof(BUSY);
/********************************************************
Check if previous block is free and combine it now.
********************************************************/
// 如果前一个块是空闲的,则将它与新的连接在一起
if ( (x = p->busy.lpPrev) != 0 && !IS_BUSY(x) )
{
_RemoveFromFree( lpHeap, x ); // 从空闲链表移出
dwRealSize += (char*)p - (char*)x;
p = x;
}
}
else
{
if ( lpHeap->lpLastBlock )
{
p->busy.lpPrev = lpHeap->lpLastBlock;
lpHeap->lpLastBlock->busy.lpNext = (LPBLOCK)((char*)p+BUSY_FLAG);
}
else
{
p->busy.lpPrev = NULL;
lpHeap->lpFirstBlock = p;
}
}
// 保留一个最小的BLOCK结构,用于记录该内存段的结束
p->busy.lpNext = lpHeap->lpLastBlock =
(LPBLOCK)((char*)p + dwRealSize - sizeof(BUSY));
lpHeap->lpLastBlock->busy.lpPrev = p;
lpHeap->lpLastBlock->busy.lpNext = (LPBLOCK)(BUSY_FLAG);
// 将新的段插入空闲链表
_InsertToFree( lpHeap, p);
}
// p 指向空闲块
if ( (char*)p->busy.lpNext-(char*)p-dwSizeNeeded > sizeof(BLOCK) )
{
// 如果p指向的空闲块较大,则从p指向的空闲块分割族够的内存块,并将剩下的放入空闲链表
x = (LPBLOCK)((char*)p + dwSizeNeeded);
p->busy.lpNext->busy.lpPrev = x;
x->busy.lpPrev = p;
x->busy.lpNext = p->busy.lpNext;
p->busy.lpNext = (LPBLOCK)((char*)x + BUSY_FLAG + ALLOC_FLAG );
_RemoveFromFree( lpHeap, p );
_InsertToFree( lpHeap, x );
}
else
{ //将p从空闲链表移出
_RemoveFromFree( lpHeap, p );
p->busy.lpNext = (LPBLOCK)((char*)p->busy.lpNext+BUSY_FLAG +ALLOC_FLAG);
}
//离开互斥段
DEBUGMSG( DEBUG_HEAPALLOC, ( "---M(0x%x)M---.\r\n", KL_GetCurrentThreadId() ) );
LeaveCriticalLock( lpHeap, TRUE );
if( dwFlags & HEAP_ZERO_MEMORY )
{
memset( (char*)p + sizeof(BUSY), 0, dwSave );
}
return (char*)p + sizeof(BUSY);
M_RETNULL:
KL_SetLastError(ERROR_NOT_ENOUGH_MEMORY);
WARNMSG( DEBUG_HEAPALLOC, ( TEXT("error HeapAlloc: Not enough memory.!\r\n") ) );
return NULL;
}
/**************************************************
声明:BOOL IsPtrValid( void FAR * lpvUsed )
参数:
lpHeap - 堆句柄指针
lpvUsed - 需要检验的指针(已分配的内存地址)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -