0% found this document useful (0 votes)
3 views3 pages

Academic Notes

This document serves as a comprehensive study guide on data structures and memory management in C, detailing memory allocation strategies, particularly focusing on dynamic memory functions like malloc, calloc, realloc, and free. It compares linear data structures, specifically arrays and singly linked lists, highlighting their trade-offs in terms of memory allocation, access speed, and cache locality. Additionally, it provides a practical implementation of a singly linked list and emphasizes the importance of memory management best practices in C programming.

Uploaded by

yashay158
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views3 pages

Academic Notes

This document serves as a comprehensive study guide on data structures and memory management in C, detailing memory allocation strategies, particularly focusing on dynamic memory functions like malloc, calloc, realloc, and free. It compares linear data structures, specifically arrays and singly linked lists, highlighting their trade-offs in terms of memory allocation, access speed, and cache locality. Additionally, it provides a practical implementation of a singly linked list and emphasizes the importance of memory management best practices in C programming.

Uploaded by

yashay158
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Document 1: Comprehensive Study Guide on Data Structures and Memory

Management in C

1. Introduction to Systems Memory and Allocation Strategies

In C programming, understanding how memory is partitioned and managed by the


operating system is foundational to writing performant applications. Program
memory is divided into several distinct segments: the text segment (containing
compiled machine code), the data segment (storing initialized global and static
variables), the stack (managing function call frames, local variables, and control
flow), and the heap (a pool of memory used for dynamic allocation during runtime).

When working with data structures whose size cannot be predetermined at


compile time, developers must rely on heap memory allocation. Dynamic memory
allocation in standard C is handled primarily through four library functions defined
within stdlib.h:

 malloc(size_t size): Allocates a single block of contiguous memory of the


specified size in bytes. The contents of the allocated memory remain
uninitialized, meaning they may contain residual garbage data from previous
operations.

 calloc(size_t num, size_t size): Allocates memory for an array of elements


and explicitly initializes all bytes to zero. While slightly slower than malloc
due to the clearing overhead, it prevents bugs related to uninitialized data.

 realloc(void *ptr, size_t new_size): Resizes a previously allocated memory


block. If the contiguous space after the current block is insu icient, the
system allocates a new block, copies the existing data, and frees the old
pointer automatically.

 free(void *ptr): Deallocates a block of heap memory, returning it to the


operating system's availability pool. Failing to invoke free on allocated
pointers results in memory leaks, which can degrade system performance
over long running sessions.

2. Linear Data Structures: Arrays vs. Singly Linked Lists

When selecting a linear data structure for sequential data storage, the choice
typically narrows down to contiguous arrays or node-based linked lists. Both
approaches o er distinct trade-o s regarding time complexity and spatial
e iciency:
Operation /
Contiguous Array Singly Linked List
Feature

Memory Static or Dynamic Dynamic (Scattered


Allocation (Contiguous) across heap)

Random Access 𝑶(𝟏) (Constant time via 𝑶(𝒏) (Linear traversal


(Indexing) pointer arithmetic) required)

Insertion at 𝑶(𝒏) (Requires shifting all 𝑶(𝟏) (Update head


Beginning elements right) pointer)

Deletion at 𝑶(𝒏) (Requires shifting all 𝑶(𝟏) (Update head


Beginning elements left) pointer and free)

Extremely high (Adjacent Poor (Nodes scattered


Cache Locality
bytes in CPU cache) across memory)

3. Implementing a Robust Singly Linked List in C

Below is a standard structural definition and traversal implementation for a singly


linked list node. Notice how each node encapsulates both the payload data and an
explicit pointer referencing the subsequent memory address:

#include <stdio.h>

#include <stdlib.h>

struct Node {

int data;

struct Node* next;

};

struct Node* createNode(int value) {

struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));


if (newNode == NULL) {

fprintf(stderr, "Fatal: Heap memory allocation failed.\n");

exit(EXIT_FAILURE);

newNode->data = value;

newNode->next = NULL;

return newNode;

void printList(struct Node* head) {

struct Node* current = head;

while (current != NULL) {

printf("[ %d ] -> ", current->data);

current = current->next;

printf("NULL\n");

4. Algorithmic Complexity and Best Practices

Always ensure that every path of execution that allocates heap memory eventually
frees that memory. In production-grade C code, memory verification tools such as
Valgrind or AddressSanitizer should be integrated into the testing pipeline to catch
dangling pointers, double frees, and bu er overflows before deployment.

You might also like