#include #include #include #include //#include #include #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)); }