271 lines
6.8 KiB
C
271 lines
6.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <time.h>
|
|
//#include <malloc.h>
|
|
#include <string.h>
|
|
|
|
#include "resource_detector.h"
|
|
|
|
#undef malloc
|
|
#undef free
|
|
#undef main
|
|
#undef fopen
|
|
#undef fclose
|
|
|
|
#include "list.h"
|
|
|
|
#define MAGIC_CODE 0x78563412
|
|
|
|
#define ADDR(addr,offset) ((addr) + (offset))
|
|
#define SET_MAGIC_CODE(addr,offset) *((int*) ADDR(addr,offset)) = MAGIC_CODE
|
|
#define MAGIC_CODE_OK(addr,offset) (*((int*) ADDR(addr,offset)) == MAGIC_CODE)
|
|
|
|
typedef struct
|
|
{
|
|
char* addr;
|
|
unsigned int size;
|
|
const char* file;
|
|
unsigned int line;
|
|
} mem_data;
|
|
|
|
typedef struct
|
|
{
|
|
FILE* addr;
|
|
const char* file_to_open;
|
|
const char* mode;
|
|
const char* file;
|
|
unsigned int line;
|
|
} file_data;
|
|
|
|
static list_admin* memlist = NULL;
|
|
static list_admin* filelist = NULL;
|
|
|
|
static int memory_compare(const void* meminfo, const void* address, size_t size)
|
|
{
|
|
mem_data* info = (mem_data*)meminfo;
|
|
char* addr = (char*)address;
|
|
return info->addr - addr;
|
|
}
|
|
|
|
static int file_compare(const void* fileinfo, const void* address, size_t size)
|
|
{
|
|
file_data* info = (file_data*)fileinfo;
|
|
FILE* addr = (FILE*)address;
|
|
return info->addr - addr;
|
|
}
|
|
|
|
|
|
static void
|
|
invalidate (mem_data* info)
|
|
{
|
|
char* user_addr;
|
|
char* raw_addr;
|
|
unsigned int size;
|
|
|
|
user_addr = info->addr;
|
|
size = info->size;
|
|
raw_addr = ADDR (user_addr, -sizeof(int));
|
|
|
|
if (!MAGIC_CODE_OK(user_addr, -sizeof(int)) || !MAGIC_CODE_OK(user_addr, size))
|
|
{
|
|
fprintf (stderr, "ERROR: addr %p (%s, line %d): out-of-bound access\n", (void*)user_addr, info->file, info->line);
|
|
}
|
|
|
|
memset (raw_addr, 0xff, size + (2 * sizeof(int)));
|
|
free (raw_addr);
|
|
}
|
|
|
|
/*
|
|
* replacement of malloc
|
|
*/
|
|
extern void*
|
|
xmalloc (unsigned int size, const char* file, unsigned int line)
|
|
{
|
|
char* raw_addr = malloc (size + (2 * sizeof(int)));
|
|
char* user_addr;
|
|
mem_data info = {NULL, 0, NULL, 0};
|
|
|
|
if (raw_addr == NULL)
|
|
{
|
|
fprintf (stderr, "ERROR: malloc failed for %d bytes (%s, line %d)\n", size, file, line);
|
|
return (NULL);
|
|
}
|
|
else
|
|
{
|
|
user_addr = ADDR (raw_addr, sizeof (int));
|
|
SET_MAGIC_CODE (raw_addr, 0);
|
|
SET_MAGIC_CODE (user_addr, size);
|
|
|
|
info.addr = user_addr;
|
|
info.size = size;
|
|
info.file = file;
|
|
info.line = line;
|
|
list_add_tail(memlist, &info);
|
|
}
|
|
return ((void*) user_addr);
|
|
}
|
|
|
|
/*
|
|
* replacement of free
|
|
*/
|
|
extern void
|
|
xfree (void* addr, const char* filename, int linenr)
|
|
{
|
|
char* user_addr = (char*) addr;
|
|
mem_data* info = NULL;
|
|
|
|
/* check if allocated memory is in our list and retrieve its info */
|
|
int index = list_index_of_special(memlist, addr, memory_compare);
|
|
info = list_get_element(memlist, index);
|
|
|
|
if (info == NULL)
|
|
{
|
|
fprintf (stderr, "ERROR: trying to free memory that was not malloc-ed (addr %p) in %s : %d\n", (void*)user_addr, filename, linenr);
|
|
return;
|
|
}
|
|
|
|
invalidate (info);
|
|
list_delete_item(memlist, index);
|
|
}
|
|
|
|
static void
|
|
print_empty_lines(int n)
|
|
{
|
|
int i;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
fprintf(stderr, "\n");
|
|
}
|
|
}
|
|
|
|
static void set_colour_red(void)
|
|
{
|
|
fprintf(stderr, "\033[10;31m");
|
|
}
|
|
static void set_colour_gray(void)
|
|
{
|
|
fprintf(stderr, "\033[22;37m");
|
|
}
|
|
static void
|
|
print_line(void)
|
|
{
|
|
fprintf (stderr, "---------------------------------------------------------\n");
|
|
}
|
|
|
|
static void
|
|
print_not_good(void)
|
|
{
|
|
set_colour_gray();
|
|
print_line();
|
|
set_colour_red();
|
|
fprintf (stderr, " # # ###\n");
|
|
fprintf (stderr, " ## # #### ##### #### #### #### ##### ###\n");
|
|
fprintf (stderr, " # # # # # # # # # # # # # # ###\n");
|
|
fprintf (stderr, " # # # # # # # # # # # # # # \n");
|
|
fprintf (stderr, " # # # # # # # ### # # # # # # \n");
|
|
fprintf (stderr, " # ## # # # # # # # # # # # ###\n");
|
|
fprintf (stderr, " # # #### # #### #### #### ##### ###\n");
|
|
set_colour_gray();
|
|
print_line();
|
|
}
|
|
|
|
/*
|
|
* writes all info of the unallocated memory
|
|
*/
|
|
static void
|
|
resource_detection (void)
|
|
{
|
|
time_t now = time (NULL);
|
|
|
|
int forgotten_frees = list_get_nr_elements(memlist);
|
|
int nr_files_open = list_get_nr_elements(filelist);
|
|
|
|
if ((forgotten_frees > 0) || (nr_files_open > 0))
|
|
{
|
|
print_empty_lines(15);
|
|
}
|
|
|
|
if (forgotten_frees > 0)
|
|
{
|
|
mem_data* info = NULL;
|
|
print_line();
|
|
fprintf (stderr, "Memory Leak Summary, generated: %s", ctime (&now));
|
|
print_not_good();
|
|
set_colour_red();
|
|
while((info = list_get_element(memlist, 0)) != NULL)
|
|
{
|
|
fprintf (stderr, "forgot to free address: %p (%d bytes) that was allocated in: %s on line: %d\n",
|
|
(void*)info->addr, info->size, info->file, info->line);
|
|
list_delete_item(memlist, 0);
|
|
}
|
|
set_colour_gray();
|
|
print_line();
|
|
print_empty_lines(1);
|
|
}
|
|
|
|
if (nr_files_open > 0)
|
|
{
|
|
file_data* info = NULL;
|
|
print_line();
|
|
fprintf (stderr, "File Management Summary, generated: %s", ctime (&now));
|
|
print_not_good();
|
|
set_colour_red();
|
|
while((info = list_get_element(filelist, 0)) != NULL)
|
|
{
|
|
fprintf (stderr, "forgot to close file: %s (ptr %p, mode \"%s\") that was opened from: %s on line: %d\n",
|
|
info->file_to_open, (void*)(info->addr), info->mode, info->file, info->line);
|
|
list_delete_item(filelist, 0);
|
|
}
|
|
set_colour_gray();
|
|
print_line();
|
|
print_empty_lines(1);
|
|
}
|
|
if ((forgotten_frees == 0) && (nr_files_open == 0))
|
|
{
|
|
printf ("\nResource checks: OK\n\n");
|
|
}
|
|
|
|
destruct_list(&memlist);
|
|
destruct_list(&filelist);
|
|
}
|
|
|
|
extern FILE*
|
|
xfopen (const char* file_to_open, const char* mode, const char* filename, int linenr)
|
|
{
|
|
file_data info = {0};
|
|
info.addr = fopen(file_to_open, mode);
|
|
if (info.addr != NULL)
|
|
{
|
|
info.file_to_open = file_to_open;
|
|
info.mode = mode;
|
|
info.file = filename;
|
|
info.line = linenr;
|
|
list_add_tail(filelist, &info);
|
|
}
|
|
return info.addr;
|
|
}
|
|
|
|
extern int
|
|
xfclose(FILE* fptr, const char* filename, int linenr)
|
|
{
|
|
int index = list_index_of_special(filelist, fptr, file_compare);
|
|
if (index < 0)
|
|
{
|
|
fprintf (stderr, "ERROR: trying to close an unopened file in %s on line number %d.\n", filename, linenr);
|
|
return -1;
|
|
}
|
|
list_delete_item(filelist, index);
|
|
return (fclose (fptr));
|
|
}
|
|
|
|
extern int
|
|
main (int argc, char* argv[])
|
|
{
|
|
atexit (resource_detection);
|
|
memlist = construct_list(sizeof(mem_data));
|
|
filelist = construct_list(sizeof(file_data));
|
|
|
|
return (xmain (argc, argv));
|
|
}
|