内存泄漏统计基于glibc

#include 
#include 
#include 
#include 
#include 
#include 

#define likely(x) __builtin_expect(!!(x), 1)

namespace MyMallocHook
{
    const static int MAX_MEMLEAK_RECORD_MAX = 10;
    const static int MAX_MEMLEAK_STACK_LV = 16;

    struct stMallocCallStack
    {
        void *addr;
        size_t size;
        void *calltrace[MAX_MEMLEAK_STACK_LV];
        int calltracelv;

        stMallocCallStack()
        {
            addr = NULL;
            size = 0;
            memset(calltrace, 0, sizeof(calltrace));
            calltracelv = 0;
        }
    };

    static unsigned int minmallocsize;
    std::vector vec_stack;

    static void *(*old_malloc_hook)(size_t, const void *);
    static void (*old_free_hook)(void *, const void *);

    static void *my_malloc_hook(size_t size, const void *caller);
    static void my_free_hook(void *ptr, const void *caller);

    static void my_replace_hook(void)
    {
        __malloc_hook = my_malloc_hook;
        __free_hook = my_free_hook;
    }

    static void my_recover_hook(void)
    {
        __malloc_hook = old_malloc_hook;
        __free_hook = old_free_hook;
    }

    static void my_backup_hook(void)
    {
        old_malloc_hook = __malloc_hook;
        old_free_hook = __free_hook;
    }

    static void *my_malloc_hook(size_t size, const void *caller)
    {
        void *result;
        my_recover_hook();
        result = malloc(size);
        stMallocCallStack stTrace;
        stTrace.addr = result;
        stTrace.size = size;
        stTrace.calltracelv = backtrace(stTrace.calltrace, MAX_MEMLEAK_STACK_LV);
        if (likely(vec_stack.size() >= MAX_MEMLEAK_RECORD_MAX))
        {
            if (size > minmallocsize)
            {

                std::sort(vec_stack.begin(), vec_stack.end(), [](const stMallocCallStack &m1, const stMallocCallStack &m2) -> bool
                          { return m1.size > m2.size; });

                minmallocsize = vec_stack[MAX_MEMLEAK_RECORD_MAX - 1].size;
                if (size > minmallocsize)
                {
                    vec_stack[MAX_MEMLEAK_RECORD_MAX - 1] = stTrace;
                }
            }
        }
        else
        {
            vec_stack.emplace_back(stTrace);
        }

        my_replace_hook();
        return result;
    }

    static void my_free_hook(void *ptr, const void *caller)
    {
        void *result;
        my_recover_hook();
        free(ptr);
        for (auto iter = vec_stack.begin(); iter != vec_stack.end(); iter++)
        {
            if ((*iter).addr == ptr)
            {
                vec_stack.erase(iter);
                break;
            }
        }
        my_replace_hook();
    }

    static void print_leak()
    {
        my_recover_hook();
        for (auto iter = vec_stack.begin(); iter != vec_stack.end(); iter++)
        {
            printf("leak heap %p, %d\n", (*iter).addr, (*iter).size);
            char **strings = backtrace_symbols((*iter).calltrace, (*iter).calltracelv);
            if (strings != NULL)
            {
                for (int i = 0; i < (*iter).calltracelv; i++)
                {
                    printf("[%02d] %s\n", i, strings[i]);
                }
                free(strings);
            }
        }
        my_replace_hook();
    }
}

void test()
{
    void *p = malloc(1000);
    //  free(p);
}
int main(void)
{
    using namespace MyMallocHook;
    my_backup_hook();
    my_replace_hook();
    test();
    print_leak();
    return 0;
}

编译选项 g++ -g -std=c++11 -rdynamic

你可能感兴趣的:(内存泄漏统计基于glibc)