C programming - basic memory management system with leak detection
This reconstructed code implements a basic memory management system with leak detection. Here's an explanation of the different parts:
1. `MemoryNode` structure: This defines a node in a linked list that tracks memory allocations. Each node contains a pointer to the allocated memory, its size, and a pointer to the next node.
2. `custom_malloc` function:
- Handles zero-sized allocations by returning NULL.
- Allocates memory using the standard `malloc`.
- Creates a new `MemoryNode` to track the allocation.
- Adds the new node to the front of the linked list.
3. `custom_free` function:
- Traverses the linked list to find the node corresponding to the pointer being freed.
- Removes the node from the list and frees both the allocated memory and the tracking node.
- If the pointer is not found in the list, it prints an error message.
4. `check_leaks` function:
- Traverses the linked list of allocations.
- If the list is empty, it reports no leaks.
- If there are nodes in the list, it reports each as a leak, printing the address and size.
- Frees all remaining allocations and their tracking nodes.
5. `main` function:
- Demonstrates usage by allocating memory, freeing some of it, and then checking for leaks.
This system helps prevent memory leaks by tracking all allocations and providing a way to check for unfreed memory. However, it's important to note that this is a simplified implementation and may not be suitable for production use without further refinement and error handling.
__________
Code:
// Structure to represent a memory allocation node
typedef struct MemoryNode {
void *ptr; // Pointer to the allocated memory
size_t size; // Size of the allocated memory
struct MemoryNode *next; // Pointer to the next node
} MemoryNode;
// Global variable to store the head of the linked list
MemoryNode *head = NULL;
// Custom malloc function
void *custom_malloc(size_t size) {
// Handle zero-sized allocations
if (size == 0) {
return NULL;
}
// Allocate memory
void *ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Memory allocation failed!\n");
return NULL;
}
// Create a new node and add it to the linked list
MemoryNode *new_node = malloc(sizeof(MemoryNode));
if (new_node == NULL) {
fprintf(stderr, "Memory allocation for tracking failed!\n");
free(ptr);
return NULL;
}
new_node->ptr = ptr;
new_node->size = size;
new_node->next = head;
head = new_node;
return ptr;
}
// Custom free function
void custom_free(void *ptr) {
if (ptr == NULL) {
return;
}
MemoryNode *current = head;
MemoryNode *previous = NULL;
// Traverse the linked list to find the node to free
while (current != NULL) {
if (current->ptr == ptr) {
// Remove the node from the list
if (previous == NULL) {
head = current->next;
} else {
previous->next = current->next;
}
// Free the memory and the node
free(current->ptr);
free(current);
return;
}
previous = current;
current = current->next;
}
fprintf(stderr, "Attempted to free untracked pointer: %p\n", ptr);
}
// Function to check for memory leaks
void check_leaks() {
MemoryNode *current = head;
if (current == NULL) {
printf("No memory leaks detected.\n");
return;
}
printf("Memory leaks detected:\n");
while (current != NULL) {
printf("Leaked memory at %p, Size: %zu bytes\n", current->ptr, current->size);
MemoryNode *temp = current;
current = current->next;
free(temp->ptr);
free(temp);
}
head = NULL;
}
// Main function to demonstrate usage
int main() {
int *data1 = (int *)custom_malloc(sizeof(int) * 5);
char *data2 = (char *)custom_malloc(sizeof(char) * 10);
custom_free(data1);
// Intentionally not freeing data2 to create a leak
check_leaks();
return 0;
}
Comments
Post a Comment