Следующий код перехватывает вызовы malloc()
, realloc()
и calloc()
для регистрации.
При вызове free()
он проверяет, была ли память ранее выделена одной из этих функций. Если нет, программа будет прекращена. Об освобождении нулевого указателя будет сообщено, но выполнение будет продолжено.
Заголовок memdebug.h
:
#undef free
#define free(PTR) memdebug_free(PTR, #PTR, __FILE__, __func__, __LINE__)
#undef malloc
#define malloc(SIZE) memdebug_log(malloc(SIZE))
#undef realloc
#define realloc(PTR, SIZE) memdebug_log(realloc(PTR, SIZE))
#undef calloc
#define calloc(COUNT, SIZE) memdebug_log(calloc(COUNT, SIZE))
#ifndef MEMDEBUG_H
#define MEMDEBUG_H
extern void memdebug_free(void *ptr, const char *ptr_arg, const char *file,
const char *func, int line);
extern void *memdebug_log(void *ptr);
#endif
Источник memdebug.c
:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef MEMDEBUG_TABLE_SIZE
// log 16k allocations by default
#define MEMDEBUG_TABLE_SIZE 0x4000
#endif
static void *alloc_table[MEMDEBUG_TABLE_SIZE];
static size_t top;
void *memdebug_log(void *ptr)
{
assert(top < sizeof alloc_table / sizeof *alloc_table);
alloc_table[top++] = ptr;
return ptr;
}
void memdebug_free(void *ptr, const char *ptr_arg, const char *file,
const char *func, int line)
{
if(!ptr)
{
fprintf(stderr,
"%s() in %s, line %i: freeing null pointer `%s` -->continue\n",
func, file, line, ptr_arg);
return;
}
for(size_t i = top; i--; )
{
if(ptr == alloc_table[i])
{
free(ptr);
--top;
if(i != top) alloc_table[i] = alloc_table[top];
return;
}
}
fprintf(stderr,
"%s() in %s, line %i: freeing invalid pointer `%s`-->exit\n",
func, file, line, ptr_arg);
exit(EXIT_FAILURE);
}