9. Common Errors and Debugging

9.1 Memory Leaks 
 Problem: 
 void createList() {
 struct Node *head = (struct Node*)malloc(sizeof(struct Node));
 head->data = 10;
 head->next = NULL;
 // MEMORY LEAK! head is lost when function returns
}
 
 Solution: 
 struct Node* createList() {
 struct Node *head = (struct Node*)malloc(sizeof(struct Node));
 head->data = 10;
 head->next = NULL;
 return head; // Return pointer to caller
}

// In main:
struct Node *myList = createList();
// ... use list ...
freeList(&myList); // Free memory when done
 
 9.2 Dereferencing NULL Pointer 
 Problem: 
 void insertAtEnd(struct Node **head, int value) {
 struct Node *temp = *head;
 while (temp->next != NULL) { // CRASH if head is NULL!
 temp = temp->next;
 }
 // ...
}
 
 Solution: 
 void insertAtEnd(struct Node **head, int value) {
 struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
 newNode->data = value;
 newNode->next = NULL;
 
 if (*head == NULL) { // Check for NULL first!
 *head = newNode;
 return;
 }
 
 struct Node *temp = *head;
 while (temp->next != NULL) {
 temp = temp->next;
 }
 temp->next = newNode;
}
 
 9.3 Lost Node References 
 Problem: 
 void deleteNode(struct Node **head, int position) {
 struct Node *temp = *head;
 for (int i = 0; i < position - 1; i++) {
 temp = temp->next;
 }
 temp->next = temp->next->next; // MEMORY LEAK! Node not freed
}
 
 Solution: 
 void deleteNode(struct Node **head, int position) {
 struct Node *temp = *head;
 for (int i = 0; i < position - 1; i++) {
 temp = temp->next;
 }
 struct Node *nodeToDelete = temp->next; // Save reference
 temp->next = nodeToDelete->next;
 free(nodeToDelete); // Free memory
}
 
 9.4 Infinite Loop in Circular List 
 Problem: 
 void display(struct Node *head) {
 struct Node *temp = head;
 while (temp != NULL) { // Never NULL in circular list!
 printf("%d ", temp->data);
 temp = temp->next;
 }
}
 
 Solution: 
 void displayCircular(struct Node *head) {
 if (head == NULL) return;
 
 struct Node *temp = head;
 do {
 printf("%d ", temp->data);
 temp = temp->next;
 } while (temp != head); // Check if back to head
}
 
 9.5 Incorrect Pointer Updates 
 Problem: 
 void insertAtBeginning(struct Node *head, int value) {
 struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
 newNode->data = value;
 newNode->next = head;
 head = newNode; // Only changes local copy!
}
 
 Solution: 
 void insertAtBeginning(struct Node **head, int value) {
 struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
 newNode->data = value;
 newNode->next = *head;
 *head = newNode; // Updates actual head pointer
}
 
 9.6 Debugging Techniques 
 Print Node Addresses 
 void debugList(struct Node *head) {
 printf("\n=== Debug Info ===\n");
 struct Node *temp = head;
 int count = 0;
 
 while (temp != NULL) {
 printf("Node %d:\n", count++);
 printf(" Address: %p\n", (void*)temp);
 printf(" Data: %d\n", temp->data);
 printf(" Next: %p\n", (void*)temp->next);
 temp = temp->next;
 }
 printf("==================\n\n");
}
 
 Check List Integrity 
 int checkListIntegrity(struct Node *head) {
 if (head == NULL) {
 return 1; // Empty list is valid
 }
 
 struct Node *slow = head;
 struct Node *fast = head;
 
 // Check for cycles
 while (fast != NULL && fast->next != NULL) {
 slow = slow->next;
 fast = fast->next->next;
 
 if (slow == fast) {
 printf("ERROR: Cycle detected!\n");
 return 0;
 }
 }
 
 printf("List integrity: OK\n");
 return 1;
}
 
 Visualize List 
 void visualizeList(struct Node *head) {
 if (head == NULL) {
 printf("NULL\n");
 return;
 }
 
 struct Node *temp = head;
 printf("HEAD → ");
 
 while (temp != NULL) {
 printf("[%d]", temp->data);
 temp = temp->next;
 if (temp != NULL) {
 printf(" → ");
 }
 }
 printf(" → NULL\n");
}
 
 9.7 Common Error Messages 
 Segmentation Fault: 
 
 Dereferencing NULL pointer 
 Accessing freed memory 
 Buffer overflow 
 
 Memory Leak: 
 
 Not freeing allocated memory 
 Losing references to nodes 
 Not calling free() on all nodes 
 
 Infinite Loop: 
 
 Wrong termination condition 
 Circular list without proper check 
 Pointer not advancing 
 
 9.8 Preventive Measures 
 // Always check malloc return value
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL) {
 fprintf(stderr, "Memory allocation failed!\n");
 return NULL;
}

// Check for NULL before dereferencing
if (head != NULL) {
 // Safe to use head->data
}

// Free all nodes before exiting
void freeList(struct Node **head) {
 struct Node *temp;
 while (*head != NULL) {
 temp = *head;
 *head = (*head)->next;
 free(temp);
 }
}

// Set pointers to NULL after freeing
free(node);
node = NULL;

// Use assertions for debugging
#include <assert.h>
assert(head != NULL); // Program stops if false