⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 heap.c

📁 不错的东西 请查看 WINCE OS
💻 C
📖 第 1 页 / 共 5 页
字号:

    // Remove the heap from the list of heaps for the current process.
    EnterCriticalSection(&csHeapList);
    for (pphp = &phpListAll ; *pphp != 0 ; pphp = &(*pphp)->phpNext) {
        if (*pphp == php) {
            *pphp = php->phpNext;
            break;
        }
    }
    LeaveCriticalSection(&csHeapList);

    // Free all VirtualAlloc'ed heap items.
    while ((pva = php->pvaList) != 0)
        HeapFree(hHeap, 0, pva+1);

#ifdef MEMTRACKING
    // If memory tracking is enabled, scan the heap and delete the tracking info.
    prgn = &php->rgn;
    do {
        pitem pit = FIRSTITEM(prgn);
        do {
            if (pit->size > 0) {
                if (pit->prgn == prgn)
                    DeleteTrackedItem(php->dwMemType, pit+1);
                else
                    DEBUGCHK(pit->prgn == 0);
                pit = (pitem)((char*)pit + pit->size);
            } else
                pit = (pitem)((char*)pit - pit->size);
        } while (pit->size);
    } while ((prgn = prgn->prgnNext) != 0);
#endif

    // Free all additional regions added to the heap.
    while ((prgn = php->rgn.prgnNext) != 0)
        DeleteRegion(prgn);

    DeleteCriticalSection(&php->cs);

#ifdef MEMTRACKING
    DeleteTrackedItem(dwHeapMemType, hHeap);
#endif
    pfnFree = php->pfnFree;
    dwRgnData = php->rgn.dwRgnData;
    pfnFree (php, (php->cbMaximum ? php->cbMaximum : CE_FIXED_HEAP_MAXSIZE), MEM_DECOMMIT, dwRgnData);
    pfnFree (php, 0, MEM_RELEASE, dwRgnData);

    DEBUGMSG(DBGFIXHP, (L"   HeapDestroy %8.8lx ==> %8.8lx\r\n", hHeap, 1));
    return TRUE;
}

UINT CompactRegion(pregion prgn)
{
    pitem pit, pitNext;
    pitem pitPrev;
    int cbMaxFree = 0;
    int cbItem;

    DEBUGMSG(DBGHEAP2, (L"   CompactRegion: 0x%08X\r\n", prgn));
    pit = pitPrev = FIRSTITEM(prgn);
    do {
        // Skip over allocated blocks (and holes)
        while ((cbItem = pit->size) > 0) {
            pitPrev = pit;
            pit = (pitem)((char*)pit + cbItem);
        }

        // Scan a possible run of free blocks and merge them.
        pitNext = MergeFreeItems (prgn, pit);
        cbItem = -pit->size;

        // if we're on the last block, free the extra pages
        if ((cbItem >= PAGE_SIZE) && !pitNext->size) {
            // move back the end marker and free the extra pages
            int cbHead = PAGE_SIZE - ((DWORD)pit & PageMask) - sizeof (item);
            int cbEx = ((cbItem - cbHead) & ~PageMask);
            pitem pitEnd = (pitem)((char*)pit + cbHead); // (pit) = ptr to tail
            DEBUGCHK (cbEx > 0);
            prgn->pitLast = pit;
            pit->size = -cbHead;
            pitEnd->size = 0;   // NOTE: this assignment must come after chaning pit->size because they might overlap
            pitEnd->cbTail = pitNext->cbTail + cbEx;
#if HEAP_SENTINELS
            pitEnd->dwSig = TAILSIG;
#endif
            DEBUGCHK (((DWORD)(pitEnd+1) & PageMask) == 0);
            DEBUGMSG(DBGHEAP2, (L"     CompactRegion: Combining tail item to make free pages 0x%08X [%06x]\r\n", pit, cbHead));
            prgn->phpOwner->pfnFree (pitEnd+1, cbEx, MEM_DECOMMIT, prgn->dwRgnData);
            cbItem = cbHead;
            pitNext = pitEnd;
        }

        if (cbItem > cbMaxFree)
            cbMaxFree = cbItem;

        pit = pitNext;
    } while (pit->size);
    prgn->cbMaxFree = cbMaxFree;
    DEBUGMSG(DBGHEAP2, (L"   CompactRegion: 0x%08X   MaxFree=0x%07X  pitFree=0x%08X\r\n", prgn, cbMaxFree, prgn->pitFree));
    return cbMaxFree;
}


UINT WINAPI HeapCompact(HANDLE hHeap, DWORD dwFlags)
{
    pheap php;
    pregion prgn;
    INT cbMaxFree;

    if (dwFlags & ~HEAP_NO_SERIALIZE) {
        DEBUGMSG(DBGFIXHP, (L"   HeapCompact %8.8lx %8.8lx ==> %8.8lx (invalid parameter)\r\n", hHeap, dwFlags, 0));
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }
    if (!hHeap) {
        SetLastError(ERROR_INVALID_PARAMETER);
        DEBUGMSG(DBGFIXHP, (L"   HeapCompact %8.8lx %8.8lx ==> %8.8lx (invalid parameter)\r\n", hHeap, dwFlags, 0));
        return 0;
    }

    php = (pheap)hHeap;

    EnterCriticalSection(&php->cs);
    cbMaxFree = 0;
    for (prgn = &php->rgn ; prgn ; prgn = prgn->prgnNext) {
        int cbFree = CompactRegion(prgn);
        if (cbFree > cbMaxFree)
            cbMaxFree = cbFree;
    }
    LeaveCriticalSection(&php->cs);
    DEBUGMSG(DBGFIXHP, (L"   HeapCompact %8.8lx %8.8lx ==> %8.8lx\r\n", hHeap, dwFlags, cbMaxFree));
    return cbMaxFree;
}


void CompactAllHeaps(void)
{
    pheap php;

    DEBUGMSG(1, (L"CompactAllHeaps: starting\r\n"));
    if (!fFullyCompacted) {
        fFullyCompacted = TRUE;
        EnterCriticalSection(&csHeapList);
        for (php = phpListAll ; php ; php = php->phpNext)
            HeapCompact((HANDLE)php, 0);
        LeaveCriticalSection(&csHeapList);
    }
    DEBUGMSG(1, (L"CompactAllHeaps: done\r\n"));
}

/*
    @doc BOTH EXTERNAL

    @func HANDLE   | GetProcessHeap | Obtains a handle to the heap of the
    calling process
*/
HANDLE WINAPI GetProcessHeap(VOID)
{
    return hProcessHeap;
}


BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
{
    pitem pitSeek, pit;
    pheap php = (pheap)hHeap;
    pregion prgn;
    BOOL bRet = FALSE;
    int cbFree;

    if ((dwFlags & ~HEAP_NO_SERIALIZE) || !hHeap || php->dwSig != HEAPSIG
            || (lpMem && lpMem < (LPCVOID)0x10000)) {
        DEBUGMSG(DBGFIXHP, (L"   HeapValidate %8.8lx: Invalid parameter\r\n", hHeap));
        return FALSE;
    }

    try {
        if (lpMem) {
            if (((DWORD)hHeap>>SECTION_SHIFT) != ((DWORD)lpMem>>SECTION_SHIFT)) {
                // The ptr has been unmapped by someone or it doesn't belong to this heap.
                if ((DWORD)lpMem>>SECTION_SHIFT) {
                    DEBUGMSG(DBGFIXHP, (L"   HeapValidate %8.8lx %8.8lx %8.8lx ==> %8.8lx\r\n", hHeap,dwFlags,lpMem,0));
                    return FALSE;
                }
                // Restore the "slot mapping" bits to the pointer.
                lpMem = (LPVOID)((DWORD)lpMem | ((DWORD)hHeap & -(1<<SECTION_SHIFT)));
            }
            pitSeek = (pitem)((char*)lpMem - sizeof(item));
            if (pitSeek->size > 0) {
#if HEAP_SENTINELS
                CheckSentinels(pitSeek, TRUE);
#endif
                if (pitSeek->size & 1) {
                    // VirtualAlloc'ed item.  Validate that the item pointer falls correctly within a
                    // 64K aligned virtual memory block and that the heap owner information in the
                    // item is correct.
                    pvaitem pva;

                    pva = (pvaitem)(((DWORD)lpMem&0xFFFF0000) + (ALIGNSIZE(sizeof(vaitem)) - sizeof(vaitem)));
                    if (pitSeek != &pva->it || pitSeek->php != php)
                        goto done;
                    // Make sure that the true size of the block is a multiple of a page.
                    if (((pitSeek->size-1 + ALIGNSIZE(sizeof(vaitem)) - sizeof(item)) & PageMask) != 0)
                        goto done;
                    bRet = TRUE;
                    goto done;

                } else {
                    // Ordinary item.  Validate that the region pointer points at a region
                    // that is part of the given heap and that the size of the block is a
                    // multiple of the heap alignment value.
                    prgn = pitSeek->prgn;
                    if (prgn->phpOwner != php || (pitSeek->size & ALIGNBYTES-1) != 0)
                        goto done;
                }
            }

        } else {
            pitSeek = NULL;
            prgn = &php->rgn;
        }

        // Walk the regions of the heap validating the linkages.  If the validation is for
        // a specific block then only the region containing that block will be scanned.

        EnterCriticalSection(&php->cs);

        do {
            pit = FIRSTITEM(prgn);
            cbFree = 0;
            do {
                if (pit->size > 0) {
                    // Allocated block or hole.  Check if this is the item we're looking for and
                    // quit if so.  Otherwise, validate the block and continue scanning.
                    if (pit == pitSeek) {
                        bRet = TRUE;
                        goto done;
                    }
                    if (pit->size & ALIGNBYTES-1) {
                        // Bogus block size.  Quit scanning now.
                        DEBUGMSG(1, (L"  HeapValidate: %08x busy item=%08x invalid block size: %08x\r\n",
                                php, pit, pit->size));
                        goto done;
                    }
                    if (pit->prgn && pit->prgn != prgn) {
                        // Invalid region pointer.  Quit scanning now.
                        DEBUGMSG(1, (L"  HeapValidate: %08x busy item=%08x invalid region: %08x SHDB %08x\r\n",
                                php, pit, pit->prgn, prgn));
                        goto done;
                    }
#if HEAP_SENTINELS
                    if (!CheckSentinels(pit, FALSE))
                        goto done;
#endif
                    // Advance to the next item.
                    pit = (pitem)((char*)pit + pit->size);

                } else if (pit->size < 0) {
                    // Free item.  Validate the item size.
                    if (pit->size & ALIGNBYTES-1) {
                        // Bogus block size.  Quit scanning now.
                        DEBUGMSG(1, (L"  HeapValidate: %08x free item=%08x invalid block size: %08x\r\n",
                                php, pit, -pit->size));
                        goto done;
                    }
                    if (pit->prgn != prgn) {
                        // Invalid region pointer.  Quit scanning now.
                        DEBUGMSG(1, (L"  HeapValidate: %08x free item=%08x invalid region: %08x SHDB %08x\r\n",
                                php, pit, pit->prgn, prgn));
                        goto done;
                    }
#if HEAP_SENTINELS
                    if (!CheckFreeSentinels(pit, FALSE))
                        goto done;
#endif
                    // Advance to the next item.
                    cbFree -= pit->size;
                    pit = (pitem)((char*)pit - pit->size);
                }
            } while (pit->size != 0);

            if (pitSeek) {
                // The item wasn't found in a scan of the heap region.
                DEBUGMSG(1, (L"  HeapValidate: %08x  item=%08x not found!\r\n", php, pitSeek));
                goto done;
            }
        }while ((prgn = prgn->prgnNext) != 0);

        bRet = TRUE;
done:  ;
    } except (EXCEPTION_EXECUTE_HANDLER) {
        bRet = FALSE;
    }

    LeaveCriticalSection(&php->cs);

#ifdef DEBUG
    if (!bRet) {
        _HeapDump(hHeap);
        DEBUGCHK(0);
    }
#endif
    DEBUGMSG(DBGFIXHP, (L"   HeapValidate %8.8lx %8.8lx %8.8lx ==> %8.8lx\r\n", hHeap,dwFlags,lpMem,1));
    return bRet;
}

#ifdef DEBUG

UINT WINAPI _HeapDump(HLOCAL hHeap) {
    UINT retval = 1;
    pheap  php = (pheap) hHeap;
    pregion prgn;
    pitem pit;
    pvaitem pva;

    try {
        if (php->dwSig != HEAPSIG) {
            DEBUGMSG(1, (TEXT("_HeapDump: %8.8lx is not a valid heap! Signature=%8.8lx\r\n"), php, php->dwSig));
            goto done;
        }
        EnterCriticalSection(&php->cs);
        DEBUGMSG(1, (TEXT("_HeapDump: %8.8lx\r\n"), php));
        DEBUGMSG(1, (TEXT(" flOptions: 0x%08X   cbMaximum: 0x%08X\r\n"), php->flOptions, php->cbMaximum));

        // Walk the region list dumping all of the items in the regions.
        prgn = &php->rgn;
        do {
            if (prgn->phpOwner != php) {
                DEBUGMSG(1, (TEXT("_HeapDump: region %8.8lx has incorrect owner (%.8.8lx)\r\n"), prgn, prgn->phpOwner));
                goto done;
            }
            DEBUGMSG(1, (TEXT("   Region: 0x%08X     cbMaxFree:     0x%08X\r\n"), prgn, prgn->cbMaxFree));
            DEBUGMSG(1, (TEXT("    pitFree: 0x%08X   pitLast:       0x%08X\r\n"), prgn->pitFree, prgn->pitLast));
            pit = FIRSTITEM(prgn);
            do {
                if (pit->size > 0) {
                    if (pit->prgn == NULL) {
                        // This is a hole.
                        DEBUGMSG(1, (TEXT("       Hole: 0x%08X size: 0x%08X\r\n"), pit, pit->size));
#if HEAP_SENTINELS
                        if (pit->dwSig != HOLESIG) {
                            DEBUGMSG(1, (TEXT("Invalid hole signature: 0x%08X SHDB 0x%08X\r\n"), pit->dwSig, HOLESIG));
                            goto done;
                        }
#endif
                    } else {
                        // This is an allocated item.
                        DEBUGMSG(1, (TEXT("       Item: 0x%08X size: 0x%08X\r\n"), pit, pit->size));
#if HEAP_SENTINELS
                        if (!CheckSentinels(pit, FALSE))
                            goto done;
#endif
                    }
                    pit = (pitem)((char*)pit + pit->size);

                } else {
                    // This is a free item.
                    DEBUGMSG(1, (TEXT("       Free: 0x%08X size: 0x%08X\r\n"), pit, -pit->size));
#if HEAP_SENTINELS
                    if (!CheckFreeSentinels(pit, FALSE))
                        goto done;
#endif
                    pit = (pitem)((char*)pit - pit->size);
                }
            } while (pit->size != 0);

            DEBUGM

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -