Files
T2-start-2025/C/t-oer-prc2-cbdb-main/development-setup/startingProject/ResourceDetector/resource_detector.c
Rens Pastoor 11b391b8a1 sync
2025-05-27 22:41:46 +02:00

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));
}