📄 sbheap.c
字号:
{
pRegion->bitvGroupLo[indGroup] &=
~(0x80000000L >> (indNext - 32));
if (--pRegion->cntRegionSize[indNext] == 0)
pHeader->bitvEntryLo &=
~(0x80000000L >> (indNext - 32));
}
}
// unlink entry from list
pNext->pEntryPrev->pEntryNext = pNext->pEntryNext;
pNext->pEntryNext->pEntryPrev = pNext->pEntryPrev;
// add next entry size to present
sizeEntry += sizeNext;
indEntry = (sizeEntry >> 4) - 1;
if (indEntry > 63)
indEntry = 63;
}
// connect leftover space with any free next entry
// add next entry to the start of the bucket list
pHead = (PENTRY)((char *)&pGroup->listHead[indEntry] - sizeof(int));
pEntry->pEntryNext = pHead->pEntryNext;
pEntry->pEntryPrev = pHead;
pHead->pEntryNext = pEntry;
pEntry->pEntryNext->pEntryPrev = pEntry;
// test entry is sole member of bucket (next == prev),
if (pEntry->pEntryNext == pEntry->pEntryPrev)
{
// if region count was zero, set bit in region vector
// set bit in header entry vector, increment region count
if (indEntry < 32)
{
if (pRegion->cntRegionSize[indEntry]++ == 0)
pHeader->bitvEntryHi |= 0x80000000L >> indEntry;
pRegion->bitvGroupHi[indGroup] |= 0x80000000L >> indEntry;
}
else
{
if (pRegion->cntRegionSize[indEntry]++ == 0)
pHeader->bitvEntryLo |= 0x80000000L >> (indEntry - 32);
pRegion->bitvGroupLo[indGroup] |= 0x80000000L >>
(indEntry - 32);
}
}
// adjust size fields of entry
pEntry->sizeFront = sizeEntry;
((PENTRYEND)((char *)pEntry + sizeEntry -
sizeof(ENTRYEND)))->sizeBack = sizeEntry;
}
return TRUE;
}
/***
*int __sbh_heapmin() - minimize heap
*
*Purpose:
* Minimize the heap by freeing any deferred group.
*
*Entry:
* __sbh_pHeaderDefer - pointer to HEADER of deferred group
* __sbh_indGroupDefer - index of GROUP to defer
*
*Exit:
* None.
*
*Exceptions:
*
*******************************************************************************/
void __cdecl __sbh_heapmin (void)
{
void * pHeapDecommit;
// if a group has been deferred, free that group
if (__sbh_pHeaderDefer)
{
// if now zero, decommit the group data heap
pHeapDecommit = (void *)((char *)__sbh_pHeaderDefer->pHeapData +
__sbh_indGroupDefer * BYTES_PER_GROUP);
VirtualFree(pHeapDecommit, BYTES_PER_GROUP, MEM_DECOMMIT);
// set bit in commit vector
__sbh_pHeaderDefer->bitvCommit |= 0x80000000 >> __sbh_indGroupDefer;
// clear entry vector for the group and header vector bit
// if needed
__sbh_pHeaderDefer->pRegion->bitvGroupLo[__sbh_indGroupDefer] = 0;
if (--__sbh_pHeaderDefer->pRegion->cntRegionSize[63] == 0)
__sbh_pHeaderDefer->bitvEntryLo &= ~0x00000001L;
// if commit vector is the initial value,
// remove the region if it is not the last
if (__sbh_pHeaderDefer->bitvCommit == BITV_COMMIT_INIT &&
__sbh_cntHeaderList > 1)
{
// free the region memory area
HeapFree(_crtheap, 0, __sbh_pHeaderDefer->pRegion);
// remove entry from header list by copying over
memmove((void *)__sbh_pHeaderDefer, (void *)(__sbh_pHeaderDefer + 1),
(int)(__sbh_pHeaderList + __sbh_cntHeaderList) -
(int)(__sbh_pHeaderDefer + 1));
__sbh_cntHeaderList--;
}
// clear deferred condition
__sbh_pHeaderDefer = NULL;
}
}
/***
*int __sbh_heap_check() - check small-block heap
*
*Purpose:
* Perform validity checks on the small-block heap.
*
*Entry:
* There are no arguments.
*
*Exit:
* Returns 0 if the small-block is okay.
* Returns < 0 if the small-block heap has an error. The exact value
* identifies where, in the source code below, the error was detected.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl __sbh_heap_check (void)
{
PHEADER pHeader;
PREGION pRegion;
PGROUP pGroup;
PENTRY pEntry;
PENTRY pNext;
PENTRY pEntryLast;
PENTRY pEntryHead;
PENTRY pEntryPage;
PENTRY pEntryPageLast;
int indHeader;
int indGroup;
int indPage;
int indEntry;
int indHead;
int sizeEntry;
int sizeTrue;
int cntAllocated;
int cntFree[64];
int cntEntries;
void * pHeapGroup;
void * pHeapPage;
void * pPageStart;
BITVEC bitvCommit;
BITVEC bitvGroupHi;
BITVEC bitvGroupLo;
BITVEC bitvEntryHi;
BITVEC bitvEntryLo;
// check validity of header list
if (IsBadWritePtr(__sbh_pHeaderList,
__sbh_cntHeaderList * sizeof(HEADER)))
return -1;
// scan for all headers in list
pHeader = __sbh_pHeaderList;
for (indHeader = 0; indHeader < __sbh_cntHeaderList; indHeader++)
{
// define region and test if valid
pRegion = pHeader->pRegion;
if (IsBadWritePtr(pRegion, sizeof(REGION)))
return -2;
// scan for all groups in region
pHeapGroup = pHeader->pHeapData;
pGroup = &pRegion->grpHeadList[0];
bitvCommit = pHeader->bitvCommit;
bitvEntryHi = 0;
bitvEntryLo = 0;
for (indGroup = 0; indGroup < GROUPS_PER_REGION; indGroup++)
{
// initialize entry vector and entry counts for group
bitvGroupHi = 0;
bitvGroupLo = 0;
cntAllocated = 0;
for (indEntry = 0; indEntry < 64; indEntry++)
cntFree[indEntry] = 0;
// test if group is committed
if ((int)bitvCommit >= 0)
{
// committed, ensure addresses are accessable
if (IsBadWritePtr(pHeapGroup, BYTES_PER_GROUP))
return -4;
// for each page in group, check validity of entries
pHeapPage = pHeapGroup;
for (indPage = 0; indPage < PAGES_PER_GROUP; indPage++)
{
// define pointers to first and past last entry
pEntry = (PENTRY)((char *)pHeapPage + ENTRY_OFFSET);
pEntryLast = (PENTRY)((char *)pEntry
+ MAX_FREE_ENTRY_SIZE);
// check front and back page sentinel values
if (*(int *)((char *)pEntry - sizeof(int)) != -1 ||
*(int *)pEntryLast != -1)
return -5;
// loop through each entry in page
do
{
// get entry size and test if allocated
sizeEntry = sizeTrue = pEntry->sizeFront;
if (sizeEntry & 1)
{
// allocated entry - set true size
sizeTrue--;
// test against maximum allocated entry size
if (sizeTrue > MAX_ALLOC_ENTRY_SIZE)
return -6;
// increment allocated count for group
cntAllocated++;
}
else
{
// free entry - determine index and increment
// count for list head checking
indEntry = (sizeTrue >> 4) - 1;
if (indEntry > 63)
indEntry = 63;
cntFree[indEntry]++;
}
// check size validity
if (sizeTrue < 0x10 || sizeTrue & 0xf
|| sizeTrue > MAX_FREE_ENTRY_SIZE)
return -7;
// check if back entry size same as front
if (((PENTRYEND)((char *)pEntry + sizeTrue
- sizeof(int)))->sizeBack != sizeEntry)
return -8;
// move to next entry in page
pEntry = (PENTRY)((char *)pEntry + sizeTrue);
}
while (pEntry < pEntryLast);
// test if last entry did not overrun page end
if (pEntry != pEntryLast)
return -8;
// point to next page in data heap
pHeapPage = (void *)((char *)pHeapPage + BYTES_PER_PAGE);
}
// check if allocated entry count is correct
if (pGroup->cntEntries != cntAllocated)
return -9;
// check validity of linked-lists of free entries
pEntryHead = (PENTRY)((char *)&pGroup->listHead[0] -
sizeof(int));
for (indHead = 0; indHead < 64; indHead++)
{
// scan through list until head is reached or expected
// number of entries traversed
cntEntries = 0;
pEntry = pEntryHead;
while ((pNext = pEntry->pEntryNext) != pEntryHead &&
cntEntries != cntFree[indHead])
{
// test if next pointer is in group data area
if ((void *)pNext < pHeapGroup || (void *)pNext >=
(void *)((char *)pHeapGroup + BYTES_PER_GROUP))
return -10;
// determine page address of next entry
pPageStart = (void *)((int)pNext &
~(BYTES_PER_PAGE - 1));
// point to first entry and past last in the page
pEntryPage = (PENTRY)((char *)pPageStart +
ENTRY_OFFSET);
pEntryPageLast = (PENTRY)((char *)pEntryPage +
MAX_FREE_ENTRY_SIZE);
// do scan from start of page
// no error checking since it was already scanned
while (pEntryPage != pEntryPageLast)
{
// if entry matches, exit loop
if (pEntryPage == pNext)
break;
// point to next entry
pEntryPage = (PENTRY)((char *)pEntryPage +
(pEntryPage->sizeFront & ~1));
}
// if page end reached, pNext was not valid
if (pEntryPage == pEntryPageLast)
return -11;
// entry valid, but check if entry index matches
// the header
indEntry = (pNext->sizeFront >> 4) - 1;
if (indEntry > 63)
indEntry = 63;
if (indEntry != indHead)
return -12;
// check if previous pointer in pNext points
// back to pEntry
if (pNext->pEntryPrev != pEntry)
return -13;
// update scan pointer and counter
pEntry = pNext;
cntEntries++;
}
// if nonzero number of entries, set bit in group
// and region vectors
if (cntEntries)
{
if (indHead < 32)
{
bitvGroupHi |= 0x80000000L >> indHead;
bitvEntryHi |= 0x80000000L >> indHead;
}
else
{
bitvGroupLo |= 0x80000000L >> (indHead - 32);
bitvEntryLo |= 0x80000000L >> (indHead - 32);
}
}
// check if list is exactly the expected size
if (pEntry->pEntryNext != pEntryHead ||
cntEntries != cntFree[indHead])
return -14;
// check if previous pointer in header points to
// last entry processed
if (pEntryHead->pEntryPrev != pEntry)
return -15;
// point to next linked-list header - note size
pEntryHead = (PENTRY)((char *)pEntryHead +
sizeof(LISTHEAD));
}
}
// test if group vector is valid
if (bitvGroupHi != pRegion->bitvGroupHi[indGroup] ||
bitvGroupLo != pRegion->bitvGroupLo[indGroup])
return -16;
// adjust for next group in region
pHeapGroup = (void *)((char *)pHeapGroup + BYTES_PER_GROUP);
pGroup++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -