コード例 #1
0
ファイル: alloc.cpp プロジェクト: sundebin/coreclr
//------------------------------------------------------------------------
// ArenaAllocator::alloateMemory:
//    Allocates memory using an `ArenaAllocator`.
//
// Arguments:
//    size - The number of bytes to allocate.
//
// Return Value:
//    A pointer to the allocated memory.
//
// Note:
//    This is the DEBUG-only version of `allocateMemory`; the release
//    version of this method is defined in the corresponding header file.
//    This version of the method has some abilities that the release
//    version does not: it may inject faults into the allocator and
//    seeds all allocations with a specified pattern to help catch
//    use-before-init problems.
void* ArenaAllocator::allocateMemory(size_t size)
{
    assert(size != 0 && (size & (sizeof(int) - 1)) == 0);

    // Ensure that we always allocate in pointer sized increments.
    size = (size_t)roundUp(size, sizeof(size_t));

    if (JitConfig.ShouldInjectFault() != 0)
    {
        // Force the underlying memory allocator (either the OS or the CLR hoster) 
        // to allocate the memory. Any fault injection will kick in.
        void* p = ClrAllocInProcessHeap(0, S_SIZE_T(1));
        if (p != nullptr)
        {
            ClrFreeInProcessHeap(0, p);
        }
        else 
        {
            NOMEM();  // Throw!
        }
    }

    void* block = m_nextFreeByte;
    m_nextFreeByte += size;

    if (m_nextFreeByte > m_lastFreeByte)
    {
        block = allocateNewPage(size);
    }

    memset(block, UninitializedWord<char>(), size);
    return block;
}
コード例 #2
0
ファイル: alloc.cpp プロジェクト: sundebin/coreclr
//------------------------------------------------------------------------
// ArenaAllocator::freeHostMemory:
//    Frees memory allocated by a previous call to `allocateHostMemory`.
//
// Arguments:
//    block - A pointer to the memory to free.
void ArenaAllocator::freeHostMemory(void* block)
{
#if defined(DEBUG)
    if (bypassHostAllocator())
    {
        ::HeapFree(GetProcessHeap(), 0, block);
    }
    else
    {
        ClrFreeInProcessHeap(0, block);
    }
#else // defined(DEBUG)
    m_memoryManager->ClrVirtualFree(block, 0, MEM_RELEASE);
#endif // !defined(DEBUG)
}
コード例 #3
0
// Free a packet allocated with DbgAlloc.
void __stdcall DbgFree(void *b, void **ppvCallstack, BOOL isArray)
{
    SCAN_IGNORE_FAULT;  // tell the static contract analysis tool to ignore FAULTS due to calls of 'new' in code called by this function
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_DEBUG_ONLY;

    if (!g_DbgEnabled) {
        if (b) // check for null pointer Win98 doesn't like being
                // called to free null pointers.
            ClrFreeInProcessHeap(0, b);
        return;
    }

    // Technically it's possible to get here without having gone through
    // DbgAlloc (since it's legal to deallocate a NULL pointer), so we
    // better check for initializtion to be on the safe side.
    if (!g_HeapInitialized)
        DbgAllocInit();

    CDA_LOCK();

    // Check all active packets still look OK.
    if (g_ConstantRecheck)
        DbgValidateActivePackets(NULL, NULL);

    // Count this call to DbgFree.
    CDA_STATS_INC(Frees);

    if (b == NULL) {
        CDA_STATS_INC(NullFrees);
        CDA_UNLOCK();
        return;
    }

    // Locate the packet header in front of the data packet.
    DbgAllocHeader *h = CDA_DATA_TO_HEADER(b);

    // Verify not calling delete [] on new, and vice versa
    //_ASSERTE (h->m_IsArray == isArray);

    // Check that the header looks OK.
    DbgValidateHeader(h);

    // Count the total number of bytes we've freed so far.
    CDA_STATS_ADD(FreeBytes, h->m_Length);

    // Unlink the packet from the live packet queue.
    if (h->m_Prev)
        h->m_Prev->m_Next = h->m_Next;
    else
        g_AllocListFirst = h->m_Next;
    if (h->m_Next)
        h->m_Next->m_Prev = h->m_Prev;
    else
        g_AllocListLast = h->m_Prev;

    // Zap our link pointers so we'll spot corruption sooner.
    h->m_Next = (DbgAllocHeader *)(UINT_PTR)CDA_INV_PATTERN;
    h->m_Prev = (DbgAllocHeader *)(UINT_PTR)CDA_INV_PATTERN;

    // Zap the tag fields in the header so we'll spot double deallocations
    // straight away.
    h->m_Magic1 = CDA_INV_PATTERN;
    *CDA_MAGIC2(h) = CDA_INV_PATTERN;

    // Poison the user's data area so that continued access to it after the
    // deallocation will likely cause an assertion that much sooner.
    if (g_PoisonPackets)
        memset(b, CDA_DEALLOC_PATTERN, h->m_Length);

    // Record the callstack of the deallocator (handy for debugging double
    // deallocation problems).
    for (unsigned i = 0; i < g_CallStackDepth; i++)
        CDA_DEALLOC_STACK(h, i) = ppvCallstack[i];

    // put the pack on the free list for a while.  Delete the one that it replaces.
    if (g_PoisonPackets) {
        DbgAllocHeader* tmp = g_AllocFreeQueue[g_AllocFreeQueueCur];
        g_AllocFreeQueue[g_AllocFreeQueueCur] = h;
        h = tmp;

        g_AllocFreeQueueCur++;
        if (g_AllocFreeQueueCur >= g_FreeQueueSize)
            g_AllocFreeQueueCur = 0;
    }

    CDA_UNLOCK();

    if (h) {
        if (g_PagePerAlloc) {
            // In page per alloc mode we decommit the pages allocated, but leave
            // them reserved so that we never reuse the same virtual addresses.
            ClrVirtualFree(h, h->m_Length + CDA_SIZEOF_HEADER() + CDA_OPT_GUARD_BYTES, MEM_DECOMMIT);
        } else
            ClrHeapFree(g_HeapHandle, 0, h);
    }
}