Implementation finished

This commit is contained in:
2024-05-15 23:38:13 +05:30
parent 13c94b0908
commit 3f76635057
4 changed files with 469 additions and 24 deletions

View File

@@ -6,7 +6,7 @@ set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(MLD_LIB libmld)
set(MLD_LIB mld)
set(TEST_APP test_app)
set(HEADER_DIR ${CMAKE_SOURCE_DIR}/include)

View File

@@ -29,7 +29,7 @@ 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);
mld_init_primitive_data_types_support(struct_db);
/*Step 2 : Create structure record for structure emp_t*/
static field_info_t emp_fields[] = {
@@ -57,29 +57,30 @@ main(int argc, char** argv) {
///*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;
/*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);
/*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;
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);
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);
joseph->p = xcalloc(object_db, "int", 1);
joseph->p = NULL;
//print_object_db(object_db);
print_object_db(object_db);
//run_mld_algorithm(object_db);
//printf("Leaked Objects : \n");
//report_leaked_objects(object_db);
run_mld_algorithm(object_db);
printf("Leaked Objects : \n");
report_leaked_objects(object_db);
return 0;
}

View File

@@ -204,6 +204,15 @@ xcalloc(object_db_t* object_db, char* struct_name, int units);
/*****API to calloc the object******/
/*****API to calloc the object******/
void
xfree(object_db_t* object_db, void* ptr);
/*****API to calloc the object******/
@@ -211,16 +220,35 @@ xcalloc(object_db_t* object_db, char* struct_name, int units);
/*****APIs to register root objects******/
void
mld_register_root_object(object_db_t* object_db,
mld_register_global_object_as_root(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);
mld_set_dynamic_object_as_root(object_db_t* object_db, void* obj_ptr);
/*****APIs to register root objects******/
/*********************************************APIs' to implement MLD algorithm*************************************************/
void
report_leaked_objects(object_db_t* object_db);
/*********************************************APIs' to implement MLD algorithm*************************************************/
/********Adding support for primitive data type********/
void
run_mld_algorithm(object_db_t* object_db);
void
mld_init_primitive_data_types_support(struct_db_t* struct_db);
/********Adding support for primitive data type********/
/*
* Declaration for OBJECT DATABASE
*/

420
src/mld.c
View File

@@ -4,6 +4,7 @@
#include "css.h"
#include <assert.h>
#include <memory.h>
#include <limits.h>
char* DATA_TYPE[] = { "UINT8", "UINT32", "INT32",
"CHAR", "OBJ_PTR", "VOID_PTR", "FLOAT",
@@ -87,7 +88,7 @@ add_structure_to_struct_db(struct_db_t* struct_db, struct_db_rec_t* struct_rec)
/******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_rec_t*
struct_db_look_up(struct_db_t* struct_db, char* struct_name) {
if (!struct_db || !struct_name)
@@ -95,6 +96,9 @@ struct_db_look_up(struct_db_t* struct_db, char* struct_name) {
struct_db_rec_t* struct_rec = struct_db->head;
if (!struct_rec)
return NULL;
unsigned int sz_db = struct_db->count;
struct_db_rec_t* desired_rec = NULL;
@@ -138,7 +142,7 @@ object_db_look_up(object_db_t* object_db,
while (i < sz_db) {
if (head->ptr == ptr) {
desired_obj = head->ptr;
desired_obj = head;
break;
}
@@ -150,3 +154,415 @@ object_db_look_up(object_db_t* object_db,
return desired_obj;
}
/******Function to lookup the object record in object db******/
/******Function to add object to OBJECT DB*******/
static void
add_object_to_object_db(object_db_t* object_db,
void* ptr,
int units,
struct_db_rec_t* struct_rec,
mld_boolean_t is_root) {
object_db_rec_t* obj_rec = object_db_look_up(object_db, ptr);
/**Don't add some object twice**/
assert(!obj_rec);
obj_rec = calloc(1, sizeof(object_db_rec_t));
obj_rec->next = NULL;
obj_rec->ptr = ptr;
obj_rec->units = units;
obj_rec->struct_rec = struct_rec;
obj_rec->is_visited = MLD_FALSE;
obj_rec->is_root = is_root;
object_db_rec_t* head = object_db->head;
if (!head) {
object_db->head = obj_rec;
obj_rec->next = NULL;
object_db->count++;
return;
}
obj_rec->next = head;
object_db->head = obj_rec;
object_db->count++;
}
void*
xcalloc(object_db_t* object_db,
char* struct_name,
int units) {
struct_db_rec_t* struct_rec = struct_db_look_up(object_db->struct_db, struct_name);
assert(struct_rec);
void* ptr = calloc(units, struct_rec->ds_size);
add_object_to_object_db(object_db, ptr, units,
struct_rec, MLD_FALSE);
/*xcalloc by default set the object as non-root*/
return ptr;
}
/******Function to add object to OBJECT DB*******/
/******Function to delete object record from object db******/
static void
delete_object_record_from_object_db(object_db_t* object_db,
object_db_rec_t* object_rec) {
assert(object_rec);
object_db_rec_t* head = object_db->head;
if (head == object_rec) {
object_db->head = object_rec->next;
free(object_rec);
return;
}
object_db_rec_t* prev = head;
head = head->next;
while (head) {
if (head != object_rec) {
prev = head;
head = head->next;
continue;
}
prev->next = head->next;
head->next = NULL;
free(head);
return;
}
}
void
xfree(object_db_t* object_db, void* ptr) {
if (!ptr)
return;
object_db_rec_t* object_rec =
object_db_look_up(object_db, ptr);
assert(object_rec);
assert(object_rec->ptr);
free(object_rec->ptr);
object_rec->ptr = NULL;
/*Delete object record from object db*/
delete_object_record_from_object_db(object_db, object_rec);
}
/******Function to delete object record from object db******/
/****Printing functions for dumping object db****/
void
print_object_rec(object_db_rec_t* obj_rec, int i) {
if (!obj_rec)
return;
printf(ANSI_COLOR_MAGENTA "|-------------------------------------------------------------------------------------------------------------|\n"ANSI_COLOR_RESET);
printf(ANSI_COLOR_YELLOW "|%-3d ptr = %-10p | next = %-10p | units = %-4d | struct_name = %-10s | is_root = %s |\n"ANSI_COLOR_RESET,
i, obj_rec->ptr, obj_rec->next, obj_rec->units, obj_rec->struct_rec->struct_name, obj_rec->is_root == MLD_TRUE? "TRUE " : "FALSE");
printf(ANSI_COLOR_MAGENTA "|-------------------------------------------------------------------------------------------------------------|\n"ANSI_COLOR_RESET);
}
void
print_object_db(object_db_t* object_db) {
object_db_rec_t* object_rec = object_db->head;
unsigned int i = 0;
printf(ANSI_COLOR_CYAN "Printing OBJECT DATABASE\n" ANSI_COLOR_RESET);
for (; object_rec; object_rec = object_rec->next) {
print_object_rec(object_rec, i++);
}
}
/****Printing functions for dumping object db****/
/*****APIs to register root objects******/
/***
This API is used to register global object of certain as root object, which are global in scope.
Object is not initialized by xcalloc() function.
***/
void
mld_register_global_object_as_root(object_db_t* object_db,
void* objptr,
char* struct_name,
unsigned int units) {
struct_db_rec_t* req_struct_rec = struct_db_look_up(object_db->struct_db, struct_name);
assert(req_struct_rec);
/*Create a new object record and add it to object database with it being a root object*/
add_object_to_object_db(object_db, objptr, units, req_struct_rec, MLD_TRUE);
}
void
mld_set_dynamic_object_as_root(object_db_t* object_db, void* obj_ptr) {
object_db_rec_t* req_obj_rec = object_db_look_up(object_db, obj_ptr);
assert(req_obj_rec != NULL);
req_obj_rec->is_root = MLD_TRUE;
}
/*****APIs to register root objects******/
/************************************************APIs' to implement MLD algorithm***************************************************/
static object_db_rec_t*
get_next_root_object(object_db_t* object_db, object_db_rec_t* last_root_object) {
object_db_rec_t* cur_obj_rec = last_root_object ? last_root_object->next : object_db->head;
//assert(cur_obj_rec);
while (cur_obj_rec) {
if (cur_obj_rec->is_root == MLD_TRUE)
return cur_obj_rec;
cur_obj_rec = cur_obj_rec->next;
}
return NULL;
}
static void
init_mld_algorithm(object_db_t* object_db) {
object_db_rec_t* cur_obj = object_db->head;
while (cur_obj) {
cur_obj->is_visited = MLD_FALSE;
cur_obj = cur_obj->next;
}
}
//DFS algorithm to explore the Graphically oriented object set...
static void
mld_explore_object_recursively(object_db_t* object_db,
object_db_rec_t* parent_obj_rec) {
unsigned int i, n_fields;
char* parent_obj_ptr = NULL,
* child_obj_offset = NULL;
void* child_object_address = NULL;
field_info_t* field_info = NULL;
object_db_rec_t* child_object_rec = NULL;
struct_db_rec_t* parent_struct_rec = parent_obj_rec->struct_rec;
/*Parent object must have already visited*/
assert(parent_obj_rec->is_visited == MLD_TRUE);
if (parent_struct_rec->n_fields == 0) {
return;
}
for (i = 0; i < parent_obj_rec->units; i++) {
parent_obj_ptr = (char*)(parent_obj_rec->ptr) + (i * parent_struct_rec->ds_size);
for (n_fields = 0; n_fields < parent_struct_rec->n_fields; n_fields++) {
field_info = &parent_struct_rec->fields[n_fields];
/*Only need to handle void* and obj_ptr*/
switch (field_info->dtype) {
case UINT8:
case UINT32:
case INT32:
case CHAR:
case FLOAT:
case DOUBLE:
case OBJ_STRUCT:
break;
case VOID_PTR:
case OBJ_PTR:
default:
/*child_obj_offset is the memory location inside parent object
where address of next level object is stored*/
child_obj_offset = parent_obj_ptr + field_info->offset;
memcpy(&child_object_address, child_obj_offset, sizeof(void*));
/*child_obj_address now stores the address of the next object in the graph.
It could be NULL, Handle that as well*/
if (!child_object_address)
continue;
child_object_rec = object_db_look_up(object_db, child_object_address);
assert(child_object_rec);
/*Since it's a valid child object of the given parent object,
explore it with leisure for memory leak*/
if (child_object_rec->is_visited == MLD_FALSE) {
child_object_rec->is_visited = MLD_TRUE;
if (field_info->dtype != VOID_PTR)/*Explore next object only when it is not a VOID_PTR*/
mld_explore_object_recursively(object_db, child_object_rec);
}
else {
continue; /*Do nothing, explore next child object*/
}
}
}
}
}
/** Public API to run MLD Algorithm **/
void
run_mld_algorithm(object_db_t* object_db) {
//Necessary initialisation...
init_mld_algorithm(object_db);
//Get the first root object...
object_db_rec_t* root_obj = get_next_root_object(object_db, NULL);
while (root_obj) {
if (root_obj->is_visited == MLD_TRUE) {
//Exploration from this node object is already done...
root_obj = get_next_root_object(object_db, root_obj);
continue;
}
root_obj->is_visited = MLD_TRUE;
mld_explore_object_recursively(object_db, root_obj);
root_obj = get_next_root_object(object_db, root_obj);
}
}
static void
mld_dump_object_rec_detail(object_db_rec_t* obj_rec) {
int n_fields = obj_rec->struct_rec->n_fields;
field_info_t* field = NULL;
int units = obj_rec->units, obj_index = 0,
field_index = 0;
for (; obj_index < units; obj_index++) {
char* current_object_ptr = (char*)(obj_rec->ptr) +
(obj_index * obj_rec->struct_rec->ds_size);
for (field_index = 0; field_index < n_fields; field_index++) {
field = &obj_rec->struct_rec->fields[field_index];
switch (field->dtype) {
case UINT8:
case INT32:
case UINT32:
printf("%s[%d]->%s = %d\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, *(int*)(current_object_ptr + field->offset));
break;
case CHAR:
printf("%s[%d]->%s = %s\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, (char*)(current_object_ptr + field->offset));
break;
case FLOAT:
printf("%s[%d]->%s = %f\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, *(float*)(current_object_ptr + field->offset));
break;
case DOUBLE:
printf("%s[%d]->%s = %f\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, *(double*)(current_object_ptr + field->offset));
break;
case OBJ_PTR:
printf("%s[%d]->%s = %p\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, (void*)*(int*)(current_object_ptr + field->offset));
break;
case OBJ_STRUCT:
/*Later*/
break;
default:
break;
}
}
}
}
void
report_leaked_objects(object_db_t* object_db) {
int i = 0;
object_db_rec_t* head;
printf("Dumping Leaked Objects\n");
for (head = object_db->head; head; head = head->next) {
if (head->is_visited == MLD_FALSE) {
print_object_rec(head, i++);
mld_dump_object_rec_detail(head);
printf("\n\n");
}
}
}
/************************************************APIs' to implement MLD algorithm***************************************************/
/********Adding support for primitive data type********/
void
mld_init_primitive_data_types_support(struct_db_t* struct_db) {
REG_STRUCT(struct_db, int, 0);
REG_STRUCT(struct_db, float, 0);
REG_STRUCT(struct_db, double, 0);
}
/********Adding support for primitive data type********/