#include <stdlib.h>
#include <execinfo.h>
#include <algorithm>
#include <vector>
#include <string.h>
#include <malloc.h>
#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<stMallocCallStack> 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
网友评论