Exemplo n.º 1
0
// Routine to check all active packets to see if they still look valid.
// Optionally, also check that the non-NULL address passed does not lie within
// any of the currently allocated packets.
void DbgValidateActivePackets(void *Start, void *End)
{
    DbgAllocHeader *h = g_AllocListFirst;

    while (h) {
        DbgValidateHeader(h);
        if (Start) {
            void *head = (void *)h;
            void *tail = (void *)&CDA_DATA(h, h->m_Length + CDA_OPT_GUARD_BYTES);
            _ASSERTE((End <= head) || (Start >= tail));
        }
        h = h->m_Next;
    }

}
Exemplo n.º 2
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);
    }
}