// Called just before process exit to report stats and check for memory
// leakages etc.
void __stdcall DbgAllocReport(__in_z __in_opt char * pString,
                              BOOL fDone,
                              BOOL fDoPrintf,
                              unsigned snapShot)
{
    STATIC_CONTRACT_NOTHROW;

    if (!g_HeapInitialized)
        return;

    CDA_LOCK();

    if (g_LogStats || g_LogDist || g_DetectLeaks || g_UsageByAllocator)
        LOG((LF_DBGALLOC, LL_ALWAYS, "------ Allocation Stats ------\n"));

    // Print out basic statistics.
    if (g_LogStats) {
        LOG((LF_DBGALLOC, LL_ALWAYS, "\n"));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Alloc calls    : %u\n", (int)g_AllocStats.m_Allocs));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Alloc failures : %u\n", (int)g_AllocStats.m_AllocFailures));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Alloc 0s       : %u\n", (int)g_AllocStats.m_ZeroAllocs));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Alloc bytes    : %u\n", (int)g_AllocStats.m_AllocBytes));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Free calls     : %u\n", (int)g_AllocStats.m_Frees));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Free NULLs     : %u\n", (int)g_AllocStats.m_NullFrees));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Free bytes     : %u\n", (int)g_AllocStats.m_FreeBytes));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Leaked allocs  : %u\n", (int)(g_AllocStats.m_Allocs - g_AllocStats.m_AllocFailures) -
             (g_AllocStats.m_Frees - g_AllocStats.m_NullFrees)));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Leaked bytes   : %u\n", (int)g_AllocStats.m_AllocBytes - g_AllocStats.m_FreeBytes));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Max allocation : %u\n", (int)g_AllocStats.m_MaxAlloc));
    }

    // Print out allocation size distribution statistics.
    if (g_LogDist) {
        LOG((LF_DBGALLOC, LL_ALWAYS, "\n"));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Alloc distrib  :\n"));
        for (unsigned i = 0; i < CDA_DIST_BUCKETS; i++)
            LOG((LF_DBGALLOC, LL_ALWAYS, "  [%3u,%3u] : %u\n", i * CDA_DIST_BUCKET_SIZE,
                 (i * CDA_DIST_BUCKET_SIZE) + (CDA_DIST_BUCKET_SIZE - 1),
                 (int)g_AllocBuckets[i]));
        LOG((LF_DBGALLOC, LL_ALWAYS, "  [%3u,---] : %u\n", CDA_MAX_DIST_SIZE + 1, (int)g_LargeAllocs));
    }

    // Print out the table of top allocators. Table is pre-sorted, the first
    // NULL entry indicates the end of the valid list.
    if (g_UsageByAllocator && g_TopAllocators) {
        LOG((LF_DBGALLOC, LL_ALWAYS, "\n"));
        LOG((LF_DBGALLOC, LL_ALWAYS, "Top allocators :\n"));
        for (unsigned i = 0; i < min(CDA_TOP_ALLOCATORS, g_TopAllocatorsSlots); i++) {
            if (g_TopAllocators[i].m_EIP == NULL)
                break;
            LOG((LF_DBGALLOC, LL_ALWAYS, "  %2u: %08X %s\n",
                 i + 1,
                 g_TopAllocators[i].m_EIP,
                 DbgSymbolize(g_TopAllocators[i].m_EIP)));
            LOG((LF_DBGALLOC, LL_ALWAYS, "       %u allocations, %u bytes total, %u bytes average size\n",
                 g_TopAllocators[i].m_Count,
                 (unsigned)g_TopAllocators[i].m_TotalBytes,
                 (unsigned)(g_TopAllocators[i].m_TotalBytes / g_TopAllocators[i].m_Count)));
        }
    }

    // Print out info for all leaked packets.
    if (g_DetectLeaks) {

        DbgAllocHeader *h = g_AllocListFirst;

        // Find first leak after snapshot point
        while (h)
        {
            if (h->m_SN > snapShot)
            {
                break;
            }
            else
            {
                h = h->m_Next;
            }
        }

        int fHaveLeaks = (h!=NULL);

        if (h) {

            // Tell the Log we had memory leaks
            LOG((LF_DBGALLOC, LL_ALWAYS, "\n"));
            LOG((LF_DBGALLOC, LL_ALWAYS, "Detected memory leaks!\n"));
            LOG((LF_DBGALLOC, LL_ALWAYS, "Leaked packets :\n"));

            // Tell the console we had memory leaks
            if (fDoPrintf)
            {
                printf("Detected memory leaks!\n");
                if (pString != NULL)
                    printf("%s\n", pString);

                printf("Leaked packets :\n");
            }
        }

        while (h) {
            if (h->m_SN > snapShot) {
                char buffer1[132];
                char buffer2[32];
                sprintf(buffer1, "#%u %08p:%u ", h->m_SN, CDA_HEADER_TO_DATA(h), (unsigned int) h->m_Length);
                unsigned i;
                for (i = 0; i < 16; i++) {
                    if (i < h->m_Length)
                        sprintf(buffer2, "%02X", (BYTE)CDA_DATA(h, i));
                    else
                        strcpy(buffer2, "  ");
                    if ((i % 4) == 3)
                        strcat_s(buffer2, _countof(buffer2), " ");
                    strcat_s(buffer1, _countof(buffer1), buffer2);
                }
                for (i = 0; i < min(16, h->m_Length); i++) {
                    sprintf(buffer2, "%c", (CDA_DATA(h, i) < 32) || (CDA_DATA(h, i) > 127) ? '.' : CDA_DATA(h, i));
                    strcat_s(buffer1, _countof(buffer1), buffer2);
                }
                LOG((LF_DBGALLOC, LL_ALWAYS, "%s\n", buffer1));
                if (fDoPrintf)
                    printf("%s\n", buffer1);

                if (g_CallStackDepth == 1) {
                    LOG((LF_DBGALLOC, LL_ALWAYS, " Allocated at %08X %s\n",
                         CDA_ALLOC_STACK(h, 0), DbgSymbolize(CDA_ALLOC_STACK(h, 0))));

                if (fDoPrintf)
                    printf(" Allocated at %p %s\n",
                         CDA_ALLOC_STACK(h, 0), DbgSymbolize(CDA_ALLOC_STACK(h, 0)));
                } else {
                    LOG((LF_DBGALLOC, LL_ALWAYS, " Allocation call stack:\n"));
                    if (fDoPrintf)
                        printf(" Allocation call stack:\n");
                    for (unsigned i = 0; i < g_CallStackDepth; i++) {
                        if (CDA_ALLOC_STACK(h, i) == NULL)
                            break;
                        LOG((LF_DBGALLOC, LL_ALWAYS, "  %08X %s\n",
                             CDA_ALLOC_STACK(h, i), DbgSymbolize(CDA_ALLOC_STACK(h, i))));
                        if (fDoPrintf)
                            printf("  %p %s\n",
                                 CDA_ALLOC_STACK(h, i), DbgSymbolize(CDA_ALLOC_STACK(h, i)));
                    }
                }
                wchar_t buf[256];
                GetModuleFileNameW(h->m_hmod, buf, 256);
                LOG((LF_DBGALLOC, LL_ALWAYS, " Base, name: %08X %S\n\n", h->m_hmod, buf));
                if (fDoPrintf)
                    printf(" Base, name: %p %S\n\n", h->m_hmod, buf);
            }

            h = h->m_Next;
        }

        if (fDoPrintf)
            fflush(stdout);

        if (fHaveLeaks && g_AssertOnLeaks)
            _ASSERTE(!"Detected memory leaks!");

    }

    if (g_LogStats || g_LogDist || g_DetectLeaks || g_UsageByAllocator) {
        LOG((LF_DBGALLOC, LL_ALWAYS, "\n"));
        LOG((LF_DBGALLOC, LL_ALWAYS, "------------------------------\n"));
    }

    CDA_UNLOCK();

    if (fDone)
    {
        DbgUnloadSymbols();
        UnsafeDeleteCriticalSection(&g_AllocMutex);
        // We won't be doing any more of our debug allocation stuff
        g_DbgEnabled=0;
    }
}
Beispiel #2
0
// Destroy the critical section
void CLRCriticalSection::Destroy()
{
    WRAPPER_NO_CONTRACT;
    UnsafeDeleteCriticalSection(&m_cs);
}
Beispiel #3
0
void STDMETHODCALLTYPE UtilExecutionEngine::DestroyLock(CRITSEC_COOKIE lock) 
{
    _ASSERTE(lock);
    UnsafeDeleteCriticalSection((CRITICAL_SECTION*)lock);
    free(lock);
}