From 13c94b09081da603a9bfb8acf79c8c0d6ee5fcf7 Mon Sep 17 00:00:00 2001 From: Hizenberg Date: Tue, 14 May 2024 20:58:31 +0530 Subject: [PATCH] Phase 1 and Phase2 implemented --- .gitignore | 5 + CMakeLists.txt | 16 ++++ app/CMakeLists.txt | 10 ++ app/app.c | 85 +++++++++++++++++ include/css.h | 12 +++ include/mld.h | 233 +++++++++++++++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 7 ++ src/mld.c | 152 +++++++++++++++++++++++++++++ 8 files changed, 520 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 app/CMakeLists.txt create mode 100644 app/app.c create mode 100644 include/css.h create mode 100644 include/mld.h create mode 100644 src/CMakeLists.txt create mode 100644 src/mld.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c5f911 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*vsidx +*.opendb +.vs +out +CMakePresets.json diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..965dd27 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.22.1) + +project(Memory-Leak-Detector VERSION 1.0.0 LANGUAGES C CXX) + +set(CMAKE_C_STANDARD 17) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) + +set(MLD_LIB libmld) +set(TEST_APP test_app) + +set(HEADER_DIR ${CMAKE_SOURCE_DIR}/include) +set(SOURCE_DIR ${CMAKE_SOURCE_DIR}/src) + +add_subdirectory(src) +add_subdirectory(app) \ No newline at end of file diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..d4496fb --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,10 @@ +set(TESTING_APP "app.c") + +add_executable(${TEST_APP} + ${TESTING_APP}) + +target_include_directories(${TEST_APP} PUBLIC + ${HEADER_DIR}) + +target_link_libraries(${TEST_APP} PUBLIC + ${MLD_LIB}) \ No newline at end of file diff --git a/app/app.c b/app/app.c new file mode 100644 index 0000000..94f2d3f --- /dev/null +++ b/app/app.c @@ -0,0 +1,85 @@ +#include "mld.h" +#include +#include +#include + +/*Application Structures*/ + +typedef struct emp_ { + + char emp_name[30]; + unsigned int emp_id; + unsigned int age; + struct emp_* mgr; + float salary; + int* p; +} emp_t; + +typedef struct student_ { + + char stud_name[32]; + unsigned int rollno; + unsigned int age; + float aggregate; + struct student_* best_colleage; +} student_t; + +int +main(int argc, char** argv) { + + /*Step 1 : Initialize a new structure database */ + struct_db_t* struct_db = calloc(1, sizeof(struct_db_t)); + //mld_init_primitive_data_types_support(struct_db); + + /*Step 2 : Create structure record for structure emp_t*/ + static field_info_t emp_fields[] = { + FIELD_INFO(emp_t, emp_name, CHAR, 0), + FIELD_INFO(emp_t, emp_id, UINT32, 0), + FIELD_INFO(emp_t, age, UINT32, 0), + FIELD_INFO(emp_t, mgr, OBJ_PTR, emp_t), + FIELD_INFO(emp_t, salary, FLOAT, 0), + FIELD_INFO(emp_t, p, OBJ_PTR, 0) + }; + /*Step 3 : Register the structure in structure database*/ + REG_STRUCT(struct_db, emp_t, emp_fields); + + static field_info_t stud_fiels[] = { + FIELD_INFO(student_t, stud_name, CHAR, 0), + FIELD_INFO(student_t, rollno, UINT32, 0), + FIELD_INFO(student_t, age, UINT32, 0), + FIELD_INFO(student_t, aggregate, FLOAT, 0), + FIELD_INFO(student_t, best_colleage, OBJ_PTR, student_t) + }; + REG_STRUCT(struct_db, student_t, stud_fiels); + + /*Step 4 : Verify the correctness of structure database*/ + print_structure_db(struct_db); + + + + ///*Working with object database*/ + ///*Step 1 : Initialize a new Object database */ + //object_db_t* object_db = calloc(1, sizeof(object_db_t)); + //object_db->struct_db = struct_db; + + ///*Step 2 : Create some sample objects, equivalent to standard + // * calloc(1, sizeof(student_t))*/ + //student_t* abhishek = xcalloc(object_db, "student_t", 1); + //mld_set_dynamic_object_as_root(object_db, abhishek); + + //student_t* shivani = xcalloc(object_db, "student_t", 1); + //strncpy(shivani->stud_name, "shivani", strlen("shivani")); + ////abhishek->best_colleage = shivani; + + //emp_t* joseph = xcalloc(object_db, "emp_t", 2); + //mld_set_dynamic_object_as_root(object_db, joseph); + //joseph->p = xcalloc(object_db, "int", 1); + + //print_object_db(object_db); + + //run_mld_algorithm(object_db); + //printf("Leaked Objects : \n"); + //report_leaked_objects(object_db); + + return 0; +} \ No newline at end of file diff --git a/include/css.h b/include/css.h new file mode 100644 index 0000000..2846dce --- /dev/null +++ b/include/css.h @@ -0,0 +1,12 @@ +#ifndef __CSS__ +#define __CSS__ + +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_BLUE "\x1b[34m" +#define ANSI_COLOR_MAGENTA "\x1b[35m" +#define ANSI_COLOR_CYAN "\x1b[36m" +#define ANSI_COLOR_RESET "\x1b[0m" + +#endif \ No newline at end of file diff --git a/include/mld.h b/include/mld.h new file mode 100644 index 0000000..dcf1cd4 --- /dev/null +++ b/include/mld.h @@ -0,0 +1,233 @@ +#ifndef __MLD__ +#define __MLD__ + +#include +#include + +/* +* Declaration for STRUCTURE DATABASE +*/ + +#ifndef __STRUCT_DB__ +#define __STRUCT_DB__ + + + +#define MAX_STRUCTURE_NAME_SIZE 128 +#define MAX_FIELD_NAME_SIZE 128 + +/**Enumeration for data types**/ + +typedef enum { + + UINT8, + UINT32, + INT32, + CHAR, + OBJ_PTR, + VOID_PTR, /* To identify void-pointer type */ + FLOAT, + DOUBLE, + OBJ_STRUCT + +}data_type_t; + +typedef enum { + + MLD_FALSE, + MLD_TRUE + +} mld_boolean_t; + +/**Enumeration for data types**/ + + + +#define FIELD_OFFSET( struct_name, field_name ) \ + (unsigned int)&(((struct_name* )0)->field_name) + +#define FIELD_SIZE( struct_name, field_name ) \ + sizeof(((struct_name* )0)->field_name) + + +/******Struture to store the information of one field of a C structure******/ + +typedef struct _field_info_ { + + char fname[MAX_FIELD_NAME_SIZE]; //Name of the field + data_type_t dtype; //Data type registered + unsigned int size; //Size of the field + unsigned int offset; //Offset of field in the structure object + + // Below field is meaningful only if dtype = OBJ_PTR, Or OBJ_STRUCT + + char nested_str_name[MAX_STRUCTURE_NAME_SIZE]; +}field_info_t; + +/******Struture to store the information of one field of a C structure******/ + + + +/******Structure to store the information of one C structure which could have 'n_fields' fields******/ + +typedef struct _struct_db_rec_ { + + struct _struct_db_rec_* next; //Pointer to next structure in db + char struct_name[MAX_STRUCTURE_NAME_SIZE]; //Name of Structure variable + unsigned int ds_size; //Size of structure object + unsigned int n_fields; //No. of fields in this structure + field_info_t* fields; //Pointer to array of fields + +} struct_db_rec_t; + +/******Structure to store the information of one C structure which could have 'n_fields' fields******/ + + +/*****Structure Data base Definition******/ + +typedef struct _struct_db_ { + + struct_db_rec_t* head; //Head of the Database + unsigned int count; //No. of records in Database + +} struct_db_t; + +/*****Structure Data base Definition******/ + + + +/**********Printing functions**********/ + +void +print_structure_rec(struct_db_rec_t* struct_rec); + +void +print_structure_db(struct_db_t* struct_db); + +/**********Printing functions**********/ + + +/******Function to add the structure record to structure db******/ + +/*return 0 on success, -1 on failure from some reason*/ +int +add_structure_to_struct_db(struct_db_t* struct_db, struct_db_rec_t* struct_rec); + +/******Function to add the structure record to structure db******/ + +/******Function to lookup the structure record in structure db******/ + +/*return pointer of struct_db_rec_t on success, NULL on failure from some reason*/ +struct_db_rec_t* +struct_db_look_up(struct_db_t* struct_db, char* struct_name); + +/******Function to lookup the structure record in structure db******/ + + +/*********Structure Registration helpint API***********/ + +/**#fld_name is used to convert the fld_name to string "fld_name" if used in #define preprocessor**/ + +#define FIELD_INFO( struct_name, fld_name, dtype, nested_struct_name ) \ + {#fld_name, dtype, FIELD_SIZE(struct_name, fld_name), \ + FIELD_OFFSET(struct_name, fld_name), #nested_struct_name } + +#define REG_STRUCT(struct_db, st_name, fields_arr) \ + do{ \ + struct_db_rec_t* rec = calloc(1, sizeof(struct_db_rec_t)); \ + rec->next = NULL; \ + strncpy(rec->struct_name, #st_name, MAX_STRUCTURE_NAME_SIZE); \ + rec->ds_size = sizeof(st_name); \ + rec->n_fields = sizeof(fields_arr)/sizeof(field_info_t); \ + rec->fields = fields_arr; \ + if( add_structure_to_struct_db(struct_db, rec)){ \ + assert(0); \ + } \ + }while(0); + + +/*********Structure Registration helpint API***********/ + +#endif + +/* +* Declaration for STRUCTURE DATABASE +*/ + + + +#ifndef __OBJECT_DB__ +#define __OJBECT_DB__ + +/* +* Declaration for OBJECT DATABASE +*/ + +typedef struct _object_db_rec_ object_db_rec_t; + +struct _object_db_rec_ { + + object_db_rec_t* next; //Pointer to next object registered in OJBECT DB + void* ptr; //Pointer to object which it registered + unsigned int units; //No. of objects created + struct_db_rec_t* struct_rec; //Structure type it belongs to... + mld_boolean_t is_visited; //Used for Graph traversal + mld_boolean_t is_root; //Is this object is Root object + +}; + +typedef struct _object_db_ { + + struct_db_t* struct_db; //Pointer to OBJECT DATABASE + object_db_rec_t* head; //Head of the DB + unsigned int count; //No. of registered OBJECT in DB + +} object_db_t; + + +/****Printing functions for dumping object db****/ + +void +print_object_rec(object_db_rec_t* obj_rec, int i); + +void +print_object_db(object_db_t* object_db); + +/****Printing functions for dumping object db****/ + + +/*****API to calloc the object******/ + + +void* +xcalloc(object_db_t* object_db, char* struct_name, int units); + + + +/*****API to calloc the object******/ + + + +/*****APIs to register root objects******/ + +void +mld_register_root_object(object_db_t* object_db, + void* objptr, + char* struct_name, + unsigned int units); + +void +set_mld_object_as_global_root(object_db_t* object_db, void* obj_ptr); + +/*****APIs to register root objects******/ + +/* +* Declaration for OBJECT DATABASE +*/ + +#endif + + + + +#endif \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..1cc5b1c --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,7 @@ +set(MLD_SRC "mld.c") + +add_library(${MLD_LIB} STATIC + ${MLD_SRC}) + +target_include_directories(${MLD_LIB} PUBLIC + ${HEADER_DIR}) \ No newline at end of file diff --git a/src/mld.c b/src/mld.c new file mode 100644 index 0000000..e032311 --- /dev/null +++ b/src/mld.c @@ -0,0 +1,152 @@ +#include +#include +#include "mld.h" +#include "css.h" +#include +#include + +char* DATA_TYPE[] = { "UINT8", "UINT32", "INT32", + "CHAR", "OBJ_PTR", "VOID_PTR", "FLOAT", + "DOUBLE", "OBJ_STRUCT" }; + +/**********Printing functions**********/ + +void +print_structure_rec(struct_db_rec_t* struct_rec) { + + if (!struct_rec) + return; + + int j = 0; + + field_info_t* field = NULL; + printf(ANSI_COLOR_CYAN "|--------------------------------------------------------------|\n" ANSI_COLOR_RESET); + printf(ANSI_COLOR_YELLOW "| %-20s | size = %-8d | #flds = %-3d |\n" ANSI_COLOR_RESET, + struct_rec->struct_name, struct_rec->ds_size, struct_rec->n_fields); + + printf(ANSI_COLOR_CYAN "|--------------------------------------------------------------|--------------------------------------------------------------------------------------|\n" ANSI_COLOR_RESET); + + for (j = 0; j < struct_rec->n_fields; j++) { + field = &struct_rec->fields[j]; + printf(" %-20s |", ""); + printf("%-3d %-20s | dtype = %-15s | size = %-5d | offset = %-6d | nstructname = %-20s |\n", + j, field->fname, DATA_TYPE[field->dtype], field->size, field->offset, field->nested_str_name); + printf(" %-20s |", ""); + printf(ANSI_COLOR_CYAN "----------------------------------------------------------------------------------------------------------------------------|\n" ANSI_COLOR_RESET); + } +} + +void +print_structure_db(struct_db_t* struct_db) { + + if (!struct_db) + return; + printf("printing STRUCTURE DATABASE\n"); + + int i = 0; + struct_db_rec_t* struct_rec = NULL; + struct_rec = struct_db->head; + printf("No of Structures Registered = %d\n", struct_db->count); + while (struct_rec) { + + /****%p format specifier is used to print value of void* pointer in hexadecimal format(prints the address value)****/ + printf("Structure No : %d (%p)\n", i++, struct_rec); + print_structure_rec(struct_rec); + struct_rec = struct_rec->next; + } +} + +/**********Printing functions**********/ + + +/******Function to add the structure record to structure db******/ + +/*return 0 on success, -1 on failure from some reason*/ +int +add_structure_to_struct_db(struct_db_t* struct_db, struct_db_rec_t* struct_rec) { + + struct_db_rec_t* head = struct_db->head; + + if (!head) { + struct_db->head = struct_rec; + struct_rec->next = NULL; + struct_db->count++; + return 0; + } + + struct_rec->next = head; + struct_db->head = struct_rec; + struct_db->count++; + return 0; +} + +/******Function to add the structure record to structure db******/ + + + +/******Function to lookup the structure record in structure db******/ + +/*return pointer of struct_db_rec_t on success, NULL on failure from some reason*/ +static struct_db_rec_t* +struct_db_look_up(struct_db_t* struct_db, char* struct_name) { + + if (!struct_db || !struct_name) + return NULL; + + struct_db_rec_t* struct_rec = struct_db->head; + + unsigned int sz_db = struct_db->count; + + struct_db_rec_t* desired_rec = NULL; + + int i = 0; + while (i < sz_db) { + + if (!strncmp(struct_rec->struct_name, struct_name, MAX_STRUCTURE_NAME_SIZE)) { + desired_rec = struct_rec; + break; + } + + struct_rec = struct_rec->next; + i++; + } + + return desired_rec; +} + +/******Function to lookup the structure record in structure db******/ + + + + + +/******Function to lookup the object record in object db******/ + + +static object_db_rec_t* +object_db_look_up(object_db_t* object_db, + void* ptr) { + + object_db_rec_t* head = object_db->head; + if (!head) + return NULL; + + unsigned int sz_db = object_db->count; + + object_db_rec_t* desired_obj = NULL; + int i = 0; + while (i < sz_db) { + + if (head->ptr == ptr) { + desired_obj = head->ptr; + break; + } + + head = head->next; + i++; + + } + + return desired_obj; +} +/******Function to lookup the object record in object db******/ \ No newline at end of file