static void doMemRealloc(RTTEST hTest)
{
    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%u reallocation, grow by 1 bytes\n", PAGE_SIZE * 2);
    size_t cbAlloc = RTRandS32Ex(1, _16K);
    void  *pvBuf   = NULL;
    RTTESTI_CHECK_RC_OK_RETV(RTMemSaferAllocZEx(&pvBuf, cbAlloc, 0));
    for (uint32_t i = 0; i <= PAGE_SIZE * 2; i++)
    {
        cbAlloc += 1;
        RTTESTI_CHECK_RC_OK_RETV(RTMemSaferReallocZEx(cbAlloc - 1, pvBuf, cbAlloc, &pvBuf, 0));
        memset(pvBuf, i & 0x7f, cbAlloc);
    }
    RTMemSaferFree(pvBuf, cbAlloc);


    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "100 random reallocations\n");
    uint8_t chFiller = 0x42;
    cbAlloc = 0;
    pvBuf   = NULL;
    for (uint32_t i = 1; i <= 100; i++)
    {
        uint32_t cbNew = RTRandS32Ex(1, _16K + (i / 4) * _16K);
        RTTESTI_CHECK_RC_OK_RETV(RTMemSaferReallocZEx(cbAlloc, pvBuf, cbNew, &pvBuf, 0));

        RTTESTI_CHECK(ASMMemIsAll8(pvBuf, RT_MIN(cbAlloc, cbNew), chFiller) == NULL);

        chFiller += 0x31;
        memset(pvBuf, chFiller, cbNew);
        cbAlloc = cbNew;
    }
    RTTESTI_CHECK_RC_OK_RETV(RTMemSaferReallocZEx(cbAlloc, pvBuf, 0, &pvBuf, 0));
    RTTESTI_CHECK(pvBuf == NULL);
}
Esempio n. 2
0
/** Constructor for tst2. */
static DECLCALLBACK(int) tst2Ctor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
{
    RTTESTI_CHECK(hMemCache == g_hMemCache);
    RTTESTI_CHECK(ASMMemIsAll8(pvObj, 256, 0) == NULL);

    if (*(bool *)pvUser)
        return VERR_RESOURCE_BUSY;

    strcat((char *)pvObj, "ctor was called\n");
    return VINF_SUCCESS;
}
Esempio n. 3
0
/**
 * Basic API checks.
 * We'll return if any of these fails.
 */
static void tst1(void)
{
    RTTestISub("Basics");
    char *psz;
    int rc = VINF_SUCCESS;

    /* RTStrAlloc */
    RTTESTI_CHECK(psz = RTStrAlloc(0));
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrAlloc(1));
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrAlloc(128));
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    /* RTStrAllocEx */
    psz = (char*)"asdfasdf";
    RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 1), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 128), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    /* RTStrRealloc */
    psz = NULL;
    RTTESTI_CHECK_RC(RTStrRealloc(&psz, 10), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !psz[0]);
    RTTESTI_CHECK(psz && !psz[9]);
    RTStrFree(psz);

    psz = NULL;
    RTTESTI_CHECK_RC(RTStrRealloc(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!psz);

    psz = NULL;
    RTTESTI_CHECK_RC(RTStrRealloc(&psz, 128), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !psz[0]);
    RTTESTI_CHECK(psz && !psz[127]);
    if (psz)
    {
        memset(psz, 'a', 127);
        RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 160), VINF_SUCCESS);
        if (RT_SUCCESS(rc) && psz)
        {
            RTTESTI_CHECK(!psz[127]);
            RTTESTI_CHECK(!psz[159]);
            RTTESTI_CHECK(ASMMemIsAll8(psz, 127, 'a') == NULL);
            memset(psz, 'b', 159);

            RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 79), VINF_SUCCESS);
            if (RT_SUCCESS(rc))
            {
                RTTESTI_CHECK(!psz[78]);
                RTTESTI_CHECK(ASMMemIsAll8(psz, 78, 'b') == NULL);

                RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 0), VINF_SUCCESS);
                RTTESTI_CHECK(!psz);
            }
        }
    }
    RTStrFree(psz);

    /* RTStrDup */
    RTTESTI_CHECK(psz = RTStrDup(""));
    RTTESTI_CHECK(psz && *psz == '\0');
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDup("abcdefghijklmnop"));
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnop"));
    RTStrFree(psz);

    /* RTStrDupEx */
    psz = NULL;
    RTTESTI_CHECK_RC(RTStrDupEx(&psz, ""), VINF_SUCCESS);
    RTTESTI_CHECK(RT_FAILURE(rc) || *psz == '\0');
    if (RT_SUCCESS(rc))
        RTStrFree(psz);

    psz = (char*)"asdfasdfasdfasdf";
    RTTESTI_CHECK_RC(rc = RTStrDupEx(&psz, "abcdefghijklmnop"), VINF_SUCCESS);
    RTTESTI_CHECK(RT_FAILURE(rc) || !RTStrCmp(psz, "abcdefghijklmnop"));
    if (RT_SUCCESS(rc))
        RTStrFree(psz);

    /* RTStrDupN */
    RTTESTI_CHECK(psz = RTStrDupN("abcdefg", 3));
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDupN("abc", 100000));
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDupN("abc", 0));
    RTTESTI_CHECK(psz && *psz == '\0');
    RTStrFree(psz);

    /* RTStrAAppend */
    RTTESTI_CHECK(psz = RTStrDup("abc"));
    RTTESTI_CHECK_RC(RTStrAAppend(&psz, "def"), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdef"));
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDup("abc"));
    RTTESTI_CHECK_RC(RTStrAAppend(&psz, ""), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTTESTI_CHECK_RC(RTStrAAppend(&psz, NULL), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTStrFree(psz);

    psz = NULL;
    RTTESTI_CHECK_RC(RTStrAAppend(&psz, "xyz"), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "xyz"));
    RTStrFree(psz);

    /* RTStrAAppendN */
    RTTESTI_CHECK(psz = RTStrDup("abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "def", 1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcd"));
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDup("abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "", 0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "", RTSTR_MAX), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, NULL, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTStrFree(psz);

    psz = NULL;
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "abc", 2), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "ab"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "cdefghijklm", 1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "defghijklm", RTSTR_MAX), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklm"));
    RTStrFree(psz);

    /* RTStrAAppendExN / RTStrAAppendExNV */
    psz = NULL;
    RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 5, "a", (size_t)1, "bc", (size_t)1, "cdefg", RTSTR_MAX, "hijkl", (size_t)2, "jklmnopqrstuvwxyz", RTSTR_MAX), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 2, NULL, (size_t)0, "", (size_t)0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 1, "-", (size_t)1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz-"));
    RTStrFree(psz);

    /* RTStrATruncate */
    psz = NULL;
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!psz);

    RTTESTI_CHECK(psz = RTStrDup(""));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS);
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDup("1234567890"));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 5), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "12345"));
    RTStrFree(psz);

    psz = NULL;
    for (uint32_t i = 0; i < 128; i++)
        RTTESTI_CHECK_RC_RETV(RTStrAAppend(&psz, "abcdefghijklmnopqrstuvwxyz"), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, sizeof("abcdefghijklmnopqrstuvwxyz") - 1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 6), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdef"));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "a"));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, ""));
    RTStrFree(psz);

}
Esempio n. 4
0
/**
 * Basic API checks.
 * We'll return if any of these fails.
 */
static void tst1(RTMEMPOOL hMemPool)
{
    void *pv;

    /* Normal alloc. */
    RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 1));
    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);

    RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 0));
    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);

    /* Zeroed allocation. */
    for (uint32_t i = 0; i < 512; i++)
    {
        RTTESTI_CHECK_RETV(pv = RTMemPoolAllocZ(hMemPool, 1024));
        RTTESTI_CHECK(ASMMemIsAllU32(pv, 1024, 0) == NULL);
        memset(pv, 'a', 1024);
        RTTESTI_CHECK_RETV(RTMemPoolRefCount(pv) == 1);
        RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
    }

    RTTESTI_CHECK_RETV(pv = RTMemPoolAllocZ(hMemPool, 0));
    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);

    /* Duped allocation. */
    static const char szTest[] = "test string abcdef";
    RTTESTI_CHECK_RETV(pv = RTMemPoolDup(hMemPool, szTest, sizeof(szTest)));
    RTTESTI_CHECK(memcmp(pv, szTest, sizeof(szTest)) == 0);
    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);

    for (uint32_t i = 0; i < 512; i++)
    {
        size_t const cb = 256 - sizeof(szTest);
        RTTESTI_CHECK_RETV(pv = RTMemPoolDupEx(hMemPool, szTest, sizeof(szTest), cb));
        RTTESTI_CHECK(memcmp(pv, szTest, sizeof(szTest)) == 0);
        RTTESTI_CHECK(ASMMemIsAll8((uint8_t *)pv + sizeof(szTest), cb, 0) == NULL);
        memset(pv, 'b', sizeof(szTest) + cb);
        RTTESTI_CHECK_RETV(RTMemPoolRefCount(pv) == 1);
        RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
    }

    /* Reallocation */
    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, NULL, 1));
    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 2));
    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);

    RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 42));
    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 32));
    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);

    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, NULL, 128));
    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 256));
    RTTESTI_CHECK_RETV(RTMemPoolRealloc(hMemPool, pv, 0) == NULL);

    /* Free (a bit hard to test) */
    RTMemPoolFree(hMemPool, NULL);
    RTMemPoolFree(hMemPool, RTMemPoolAlloc(hMemPool, 42));

    /* Memory referencing. */
    for (uint32_t i = 1; i <= 4096; i *= 3)
    {
        void *pv2;
        RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, i));
        RTTESTI_CHECK(RTMemPoolRefCount(pv) == 1);
        memset(pv, 'a', i);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv));
        RTTESTI_CHECK(RTMemPoolRetain(pv) == 2);
        RTTESTI_CHECK(RTMemPoolRefCount(pv) == 2);
        RTTESTI_CHECK(RTMemPoolRetain(pv) == 3);
        RTTESTI_CHECK(RTMemPoolRefCount(pv) == 3);
        RTTESTI_CHECK(RTMemPoolRetain(pv) == 4);
        RTTESTI_CHECK(RTMemPoolRefCount(pv) == 4);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv));
        RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv) == 3);
        RTTESTI_CHECK(RTMemPoolRefCount(pv) == 3);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv));
        RTTESTI_CHECK(RTMemPoolRetain(pv) == 4);
        RTTESTI_CHECK(RTMemPoolRefCount(pv) == 4);
        RTTESTI_CHECK(RTMemPoolRetain(pv) == 5);
        RTTESTI_CHECK(RTMemPoolRefCount(pv) == 5);
        RTTESTI_CHECK(RTMemPoolRetain(pv) == 6);
        RTTESTI_CHECK(RTMemPoolRefCount(pv) == 6);
        RTTESTI_CHECK(RTMemPoolRelease(NIL_RTMEMPOOL, pv) == 5);
        RTTESTI_CHECK(RTMemPoolRelease(NIL_RTMEMPOOL, pv) == 4);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv));

        for (uint32_t cRefs = 3;; cRefs--)
        {
            RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv) == cRefs);
            if (cRefs == 0)
                break;
            RTTESTI_CHECK(RTMemPoolRefCount(pv) == cRefs);
            RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x cRefs=%d\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv, cRefs));
            for (uint32_t j = 0; j < 42; j++)
            {
                RTTESTI_CHECK_RETV(pv2 = RTMemPoolAlloc(hMemPool, i));
                RTTESTI_CHECK_RETV(pv2 != pv);
                memset(pv2, 'f', i);
                RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv2) == 0);
                RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x cRefs=%d\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv, cRefs));
            }
        }
    }
}
/**
 * Internal free.
 */
RTDECL(void) rtR3MemFree(const char *pszOp, RTMEMTYPE enmType, void *pv, void *pvCaller, RT_SRC_POS_DECL)
{
    /*
     * Simple case.
     */
    if (!pv)
        return;

    /*
     * Check watch points.
     */
    for (unsigned i = 0; i < RT_ELEMENTS(gapvRTMemFreeWatch); i++)
        if (gapvRTMemFreeWatch[i] == pv)
            RTAssertDoPanic();

#ifdef RTALLOC_EFENCE_TRACE
    /*
     * Find the block.
     */
    PRTMEMBLOCK pBlock = rtmemBlockRemove(pv);
    if (pBlock)
    {
        if (gfRTMemFreeLog)
            RTLogPrintf("RTMem %s: pv=%p pvCaller=%p cbUnaligned=%#x\n", pszOp, pv, pvCaller, pBlock->cbUnaligned);

# ifdef RTALLOC_EFENCE_NOMAN_FILLER
        /*
         * Check whether the no man's land is untouched.
         */
#  ifdef RTALLOC_EFENCE_IN_FRONT
        void *pvWrong = ASMMemIsAll8((char *)pv + pBlock->cbUnaligned,
                                     RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) - pBlock->cbUnaligned,
                                     RTALLOC_EFENCE_NOMAN_FILLER);
#  else
        /* Alignment must match allocation alignment in rtMemAlloc(). */
        void  *pvWrong   = ASMMemIsAll8((char *)pv + pBlock->cbUnaligned,
                                        pBlock->cbAligned - pBlock->cbUnaligned,
                                        RTALLOC_EFENCE_NOMAN_FILLER);
        if (pvWrong)
            RTAssertDoPanic();
        pvWrong = ASMMemIsAll8((void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK),
                               RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) - pBlock->cbAligned,
                               RTALLOC_EFENCE_NOMAN_FILLER);
#  endif
        if (pvWrong)
            RTAssertDoPanic();
# endif

# ifdef RTALLOC_EFENCE_FREE_FILL
        /*
         * Fill the user part of the block.
         */
        memset(pv, RTALLOC_EFENCE_FREE_FILL, pBlock->cbUnaligned);
# endif

# if defined(RTALLOC_EFENCE_FREE_DELAYED) && RTALLOC_EFENCE_FREE_DELAYED > 0
        /*
         * We're doing delayed freeing.
         * That means we'll expand the E-fence to cover the entire block.
         */
        int rc = RTMemProtect(pv, pBlock->cbAligned, RTMEM_PROT_NONE);
        if (RT_SUCCESS(rc))
        {
            /*
             * Insert it into the free list and process pending frees.
             */
            rtmemBlockDelayInsert(pBlock);
            while ((pBlock = rtmemBlockDelayRemove()) != NULL)
            {
                pv = pBlock->Core.Key;
#  ifdef RTALLOC_EFENCE_IN_FRONT
                void  *pvBlock = (char *)pv - RTALLOC_EFENCE_SIZE;
#  else
                void  *pvBlock = (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK);
#  endif
                size_t cbBlock = RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE;
                rc = RTMemProtect(pvBlock, cbBlock, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
                if (RT_SUCCESS(rc))
                    RTMemPageFree(pvBlock, RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE);
                else
                    rtmemComplain(pszOp, "RTMemProtect(%p, %#x, RTMEM_PROT_READ | RTMEM_PROT_WRITE) -> %d\n", pvBlock, cbBlock, rc);
                rtmemBlockFree(pBlock);
            }
        }
        else
            rtmemComplain(pszOp, "Failed to expand the efence of pv=%p cb=%d, rc=%d.\n", pv, pBlock, rc);

# else /* !RTALLOC_EFENCE_FREE_DELAYED */

        /*
         * Turn of the E-fence and free it.
         */
#  ifdef RTALLOC_EFENCE_IN_FRONT
        void *pvBlock = (char *)pv - RTALLOC_EFENCE_SIZE;
        void *pvEFence = pvBlock;
#  else
        void *pvBlock = (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK);
        void *pvEFence = (char *)pv + pBlock->cb;
#  endif
        int rc = RTMemProtect(pvEFence, RTALLOC_EFENCE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
        if (RT_SUCCESS(rc))
            RTMemPageFree(pvBlock, RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE);
        else
            rtmemComplain(pszOp, "RTMemProtect(%p, %#x, RTMEM_PROT_READ | RTMEM_PROT_WRITE) -> %d\n", pvEFence, RTALLOC_EFENCE_SIZE, rc);
        rtmemBlockFree(pBlock);

# endif /* !RTALLOC_EFENCE_FREE_DELAYED */
    }
    else
        rtmemComplain(pszOp, "pv=%p not found! Incorrect free!\n", pv);

#else /* !RTALLOC_EFENCE_TRACE */

    /*
     * We have no size tracking, so we're not doing any freeing because
     * we cannot if the E-fence is after the block.
     * Let's just expand the E-fence to the first page of the user bit
     * since we know that it's around.
     */
    int rc = RTMemProtect((void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK), PAGE_SIZE, RTMEM_PROT_NONE);
    if (RT_FAILURE(rc))
        rtmemComplain(pszOp, "RTMemProtect(%p, PAGE_SIZE, RTMEM_PROT_NONE) -> %d\n", (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK), rc);
#endif /* !RTALLOC_EFENCE_TRACE */
}