๐ง 17. Dynamic Memory Allocation
17.1 What Is Dynamic Memory Allocation?
Dynamic memory allocation lets a C program request storage while the program is running. This is useful when the required amount of memory is not known when the source code is written.
Fixed-size storage
Use ordinary variables and fixed-size arrays when the required storage is known in advance.
Dynamic storage
Request storage at runtime when the program discovers how much data it needs.
17.2 Why Do We Need Dynamic Memory?
- The number of elements may be known only after input is read.
- A program may need storage that grows or shrinks during execution.
- Large or variable data structures can be created only when required.
- Dynamic storage is fundamental to linked lists, trees, dynamic arrays and many real programs.
n, a fixed array such as int a[1000] may reserve more space than necessary. Dynamic allocation can request storage for exactly the required number of elements.17.3 Static/Automatic vs Dynamic Storage
| Ordinary / Automatic Storage | Dynamic Storage |
|---|---|
| Size is usually determined by the declaration. | Size is requested during execution. |
| Lifetime is managed automatically for automatic objects. | Programmer controls the allocation and release. |
Example: int a[10]; | Example: int *a = malloc(10 * sizeof *a); |
No free() is required for an ordinary automatic array. | The allocated block must eventually be released with free(). |
17.4 Stack and Heap โ A Practical Mental Model
Automatic local objects are commonly associated with stack storage, while memory returned by malloc(), calloc() and realloc() comes from dynamically allocated storage, commonly called the heap.
Important: โstackโ and โheapโ are useful practical models, but the exact implementation details are determined by the C implementation.
17.5 malloc() โ Request a Block of Bytes
malloc() allocates a block of memory containing the requested number of bytes. Its contents are indeterminate; the function does not initialize the allocated bytes for you.
#include <stdlib.h>
int *p = malloc(5 * sizeof *p);
sizeof *p instead of repeating the pointed-to type. It stays correct if the pointer type changes.17.6 The malloc() Lifecycle
int *p;p = malloc(n * sizeof *p);if (p == NULL)p[i]free(p);17.7 A Safe malloc() Example
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
scanf("%d", &n);
int *a = malloc((size_t)n * sizeof *a);
if (a == NULL)
return 1;
for (int i = 0; i < n; i++)
a[i] = i + 1;
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
free(a);
return 0;
}
17.8 malloc() Does Not Initialize Your Data
Reading an allocated object before storing a valid value into it can be invalid because the allocated bytes do not automatically contain useful initial values.
malloc() means โgive me an array filled with zero.โ It means โgive me a block of at least this many bytes.โ17.9 calloc() โ Allocate and Zero-Initialize
calloc(count, size) allocates space for an array of count objects, each of size bytes, and initializes the allocated bytes to zero.
int *a = calloc(5, sizeof *a);
For ordinary integer arrays, this gives elements whose initial representation is all-bits-zero; for portable C teaching, use the function according to its specified byte-zero initialization rather than treating it as a universal โzero every possible typeโ rule.
17.10 malloc() vs calloc()
| Function | Arguments | Initialization | Typical use |
|---|---|---|---|
malloc(bytes) | Total bytes | Allocated bytes are not initialized | When you will assign values yourself |
calloc(count, size) | Number ร size | Allocated bytes are initialized to zero | When zero-initialized storage is useful |
17.11 realloc() โ Resize an Existing Allocation
realloc() changes the size of a previously allocated block. The block may stay at the same address or move to a different address.
int *tmp = realloc(a, new_count * sizeof *a);
realloc().17.12 Why a Temporary Pointer Matters
int *tmp = realloc(a, new_count * sizeof *a);
if (tmp != NULL) {
a = tmp;
} else {
/* a is still valid here */
}
Assigning realloc() directly to the only pointer can lose the original pointer if resizing fails. A temporary pointer lets you handle failure safely.
17.13 realloc() โ What Can Change?
- The allocation may grow in place.
- The allocation may move to a new location.
- Existing contents are preserved up to the smaller of the old and new sizes.
- When the new size is larger, the additional part has indeterminate values.
- On failure for a nonzero requested size, the original allocation remains valid.
17.14 free() โ Release the Allocation
free(ptr) releases memory previously obtained from an allocation function. After freeing the block, the pointer value should not be dereferenced.
free(p);
p = NULL;
NULL after freeing can help prevent accidental reuse through that pointer.17.15 What Does NULL Mean Here?
If an allocation function returns NULL, the requested allocation was not successful. A null pointer must not be dereferenced.
int *p = malloc(n * sizeof *p);
if (p == NULL) {
printf("Allocation failed\n");
return 1;
}
17.16 Dynamic Arrays
A pointer returned by an allocation function can be indexed using normal array notation.
int *a = malloc(n * sizeof *a);
if (a != NULL) {
a[0] = 10;
a[1] = 20;
}
free(a);
The expression a[i] is equivalent to *(a + i). The allocation must contain enough space for every accessed element.
17.17 Dynamic Array Representation
The pointer stores the address of the first element. The allocation itself contains the array elements.
17.18 Dynamically Allocated Strings
Strings are character arrays ending in '\0'. Dynamic allocation therefore needs room for the terminator.
const char *source = "CodeBhavya";
size_t n = strlen(source) + 1;
char *copy = malloc(n);
if (copy != NULL) {
strcpy(copy, source);
printf("%s\n", copy);
free(copy);
}
When using string functions, include <string.h> and make sure the destination has enough capacity.
17.19 Dynamic Structures
struct Student {
int roll;
float marks;
};
struct Student *s = malloc(sizeof *s);
if (s != NULL) {
s->roll = 101;
s->marks = 86.5f;
free(s);
}
Use -> when accessing a structure through a pointer.
17.20 Dynamic Array of Structures
struct Student *students =
malloc(n * sizeof *students);
if (students != NULL) {
students[0].roll = 101;
students[0].marks = 86.5f;
}
free(students);
This pattern is useful for runtime-sized collections of records.
17.21 Dynamic 2D Data โ Choose a Representation
There is more than one way to represent dynamically allocated two-dimensional data. A beginner-friendly approach is an array of row pointers, while a single contiguous block can offer simpler memory ownership and better locality.
int *matrix = malloc(rows * cols * sizeof *matrix);
if (matrix != NULL) {
matrix[r * cols + c] = 42;
}
free(matrix);
Contiguous block
One allocation; access with r * cols + c.
Array of pointers
Rows can be allocated separately, allowing more flexible row sizes but requiring multiple allocations and releases.
17.22 Allocation Size โ Use sizeof Correctly
int *a = malloc(n * sizeof *a);
double *b = malloc(n * sizeof *b);
struct Student *s = malloc(n * sizeof *s);
This avoids hard-coding type sizes. For byte-count calculations involving an object count, use an appropriate unsigned size type such as size_t.
17.23 Allocation Failure Is Also a Program State
A robust program treats allocation failure as a possible runtime condition. It should decide what to do rather than immediately dereferencing the returned pointer.
NULL; check before dereferencing and handle the failure according to the program's requirements.17.24 Memory Leak
A memory leak occurs when dynamically allocated memory is no longer reachable by the program and therefore cannot be released.
int *p = malloc(100 * sizeof *p);
/* if p is overwritten or lost without free(p),
the allocation can leak */
17.25 Dangling Pointer
A dangling pointer is a pointer that refers to storage whose lifetime has ended.
int *p = malloc(sizeof *p);
if (p != NULL) {
*p = 25;
free(p);
p = NULL;
}
The important rule is not to dereference the old pointer after free().
17.26 Double Free
A double free occurs when the same allocation is released more than once. This is invalid and can lead to serious runtime failures.
free(p);
p = NULL;
/* Do not free the same allocation again. */
17.27 Use-After-Free
Use-after-free means accessing an allocation after it has been released.
free(p);
/* *p = 10; // invalid */
17.28 The Complete Dynamic Memory Workflow
n * sizeof *pmalloc / callocp != NULLrealloc with a temporary pointerfree(p)17.29 malloc(), calloc(), realloc(), free() โ Quick Comparison
| Function | Purpose | Important point |
|---|---|---|
malloc() | Allocate a byte block | Contents are not initialized |
calloc() | Allocate an array of objects | Allocated bytes are zero-initialized |
realloc() | Resize an allocation | Block may move; use a temporary pointer |
free() | Release an allocation | Do not access the block afterward |
17.30 Common Dynamic Memory Mistakes
โ No NULL check
Dereferencing a failed allocation is invalid.
โ Wrong size
Allocate enough bytes for every object, using sizeof.
โ Lost pointer
Overwriting the only pointer can create a memory leak.
โ Unsafe realloc
Use a temporary pointer when the old allocation must be preserved on failure.
โ Use-after-free
Never read or write through a pointer to released storage.
โ Double free
Release each allocation only once.
17.31 Dynamic Memory Problem-Solving Method
- Determine how many objects are required.
- Calculate the required byte count.
- Allocate with
malloc()orcalloc(). - Check for
NULL. - Initialize before reading values.
- Stay within the allocated bounds.
- Use
realloc()carefully if the size changes. - Release every successful allocation exactly once.
malloc(). Always think in three questions: How much memory? Who owns it? When is its lifetime finished?17.32 Quick Revision
๐ calloc() โ Allocates and zero-initializes bytes
๐ realloc() โ Resizes an allocation
๐ free() โ Releases memory
๐ NULL โ Indicates a null pointer
๐ Heap โ Commonly used for dynamic storage
๐ Memory leak โ Allocated memory is not released
๐ Dangling pointer โ Pointer refers to an object whose lifetime has ended
๐ Use-after-free โ Accessing freed memory
๐ sizeof *ptr โ Useful for type-safe allocation sizing
๐ฌ Dynamic Memory โ Allocation Lifecycle
Follow the complete lifecycle from requesting heap memory to releasing it safely.
๐ฌ Dynamic Memory Lifecycle Visualizer
The active card shows the current stage of safe dynamic-memory use.
๐ Program Tracing โ Dynamic Memory Allocation
Trace allocation, initialization, safe resizing with a temporary pointer, and release.
โ
17.33 Quick MCQs
Select an answer first, then click Check Answer. A correct choice becomes green. If the answer is wrong, your choice becomes red and the correct option becomes green. The explanation appears below.
malloc() allocates a block of storage whose bytes have indeterminate values until the program initializes them.
calloc() allocates storage for an array of elements and initializes the allocated bytes to zero.
realloc() changes the size of a previously allocated block and may return a different address.
free() releases storage obtained from the dynamic allocation functions.
A NULL pointer result indicates allocation failure.
A memory leak occurs when dynamically allocated storage remains allocated but the program loses the ability to free it.
A dangling pointer retains an address to an object or allocation that no longer exists.
If realloc() fails it returns NULL and the original allocation is still valid. A temporary pointer preserves access to that original block.
17.34 ๐ฏ Practice Problems
Practice allocation, arrays, strings, structures, matrices, realloc(), allocation checks, and memory-leak prevention. Use ๐ป Solve It Yourself first, open Hint only when needed, and use Show Program after attempting the problem.
Problem 1: Allocate memory dynamically for one integer and store a value in it.
Input: One integer.
Output: Print the stored integer.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int value;
scanf("%d", &value);
int *p = malloc(sizeof *p);
if (p == NULL)
return 1;
*p = value;
printf("%d", *p);
free(p);
return 0;
}
Problem 2: Dynamically allocate an array of n integers and initialize it with 1 to n.
Input: One positive integer n.
Output: Print the n initialized values.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
if (n <= 0)
return 0;
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
arr[i] = i + 1;
for (int i = 0; i < n; i++)
{
if (i > 0)
printf(" ");
printf("%d", arr[i]);
}
free(arr);
return 0;
}
Problem 3: Read n numbers into a dynamically allocated array and find their sum.
Input: n followed by n integers.
Output: Print the sum.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
long long sum = 0;
scanf("%d", &n);
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
sum += arr[i];
}
printf("%lld", sum);
free(arr);
return 0;
}
Problem 4: Find the largest element in a dynamically allocated array.
Input: n greater than 0 followed by n integers.
Output: Print the largest value.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
int maximum = arr[0];
for (int i = 1; i < n; i++)
{
if (arr[i] > maximum)
maximum = arr[i];
}
printf("%d", maximum);
free(arr);
return 0;
}
Problem 5: Find the smallest element in a dynamically allocated array.
Input: n greater than 0 followed by n integers.
Output: Print the smallest value.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
int minimum = arr[0];
for (int i = 1; i < n; i++)
{
if (arr[i] < minimum)
minimum = arr[i];
}
printf("%d", minimum);
free(arr);
return 0;
}
Problem 6: Reverse a dynamically allocated array.
Input: n followed by n integers.
Output: Print the reversed array.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
for (int left = 0, right = n - 1; left < right; left++, right--)
{
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
for (int i = 0; i < n; i++)
{
if (i > 0)
printf(" ");
printf("%d", arr[i]);
}
free(arr);
return 0;
}
Problem 7: Use calloc() to create an array of integers and display its initial values.
Input: One positive integer n.
Output: Print n zero values separated by spaces.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
int *arr = calloc((size_t)n, sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
{
if (i > 0)
printf(" ");
printf("%d", arr[i]);
}
free(arr);
return 0;
}
Problem 8: Use realloc() to increase the size of an integer array.
Input: Initial size n, n integers, new size m where m >= n, followed by m-n additional integers.
Output: Print all m values.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, m;
scanf("%d", &n);
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
scanf("%d", &m);
int *temp = realloc(arr, (size_t)m * sizeof *arr);
if (temp == NULL)
{
free(arr);
return 1;
}
arr = temp;
for (int i = n; i < m; i++)
scanf("%d", &arr[i]);
for (int i = 0; i < m; i++)
{
if (i > 0)
printf(" ");
printf("%d", arr[i]);
}
free(arr);
return 0;
}
Problem 9: Use realloc() to reduce the size of an array.
Input: Initial size n, n integers, then new size m where 0 < m <= n.
Output: Print the first m values retained in the resized block.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, m;
scanf("%d", &n);
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
scanf("%d", &m);
int *temp = realloc(arr, (size_t)m * sizeof *arr);
if (temp == NULL)
{
free(arr);
return 1;
}
arr = temp;
for (int i = 0; i < m; i++)
{
if (i > 0)
printf(" ");
printf("%d", arr[i]);
}
free(arr);
return 0;
}
Problem 10: Dynamically allocate memory for a string and store a user-provided string.
Input: One line of text.
Output: Print the dynamically stored string.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char buffer[300];
fgets(buffer, sizeof(buffer), stdin);
buffer[strcspn(buffer, "\n")] = '\0';
char *text = malloc(strlen(buffer) + 1);
if (text == NULL)
return 1;
strcpy(text, buffer);
printf("%s", text);
free(text);
return 0;
}
Problem 11: Dynamically allocate a structure and access its members.
Input: Student roll number and marks.
Output: Print the stored members.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
struct Student
{
int roll;
float marks;
};
int main()
{
struct Student *s = malloc(sizeof *s);
if (s == NULL)
return 1;
scanf("%d %f", &s->roll, &s->marks);
printf("%d %.1f", s->roll, s->marks);
free(s);
return 0;
}
Problem 12: Dynamically allocate an array of structures.
Input: n followed by n student records: roll and marks.
Output: Print all student records.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
struct Student
{
int roll;
float marks;
};
int main()
{
int n;
scanf("%d", &n);
struct Student *students = malloc((size_t)n * sizeof *students);
if (students == NULL)
return 1;
for (int i = 0; i < n; i++)
scanf("%d %f", &students[i].roll, &students[i].marks);
for (int i = 0; i < n; i++)
{
if (i > 0)
printf("\n");
printf("%d %.1f", students[i].roll, students[i].marks);
}
free(students);
return 0;
}
Problem 13: Create a dynamically allocated 2D matrix.
Input: Rows r, columns c, followed by r*c integers.
Output: Print the matrix.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r, c;
scanf("%d %d", &r, &c);
int **matrix = malloc((size_t)r * sizeof *matrix);
if (matrix == NULL)
return 1;
for (int i = 0; i < r; i++)
{
matrix[i] = malloc((size_t)c * sizeof *matrix[i]);
if (matrix[i] == NULL)
{
for (int j = 0; j < i; j++)
free(matrix[j]);
free(matrix);
return 1;
}
}
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
scanf("%d", &matrix[i][j]);
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
if (j > 0)
printf(" ");
printf("%d", matrix[i][j]);
}
if (i < r - 1)
printf("\n");
}
for (int i = 0; i < r; i++)
free(matrix[i]);
free(matrix);
return 0;
}
Problem 14: Add two dynamically allocated matrices.
Input: Rows r, columns c, first matrix values, then second matrix values.
Output: Print the sum matrix.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r, c;
scanf("%d %d", &r, &c);
size_t count = (size_t)r * (size_t)c;
int *a = malloc(count * sizeof *a);
int *b = malloc(count * sizeof *b);
int *sum = malloc(count * sizeof *sum);
if (a == NULL || b == NULL || sum == NULL)
{
free(a);
free(b);
free(sum);
return 1;
}
for (size_t i = 0; i < count; i++)
scanf("%d", &a[i]);
for (size_t i = 0; i < count; i++)
scanf("%d", &b[i]);
for (size_t i = 0; i < count; i++)
sum[i] = a[i] + b[i];
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
if (j > 0)
printf(" ");
printf("%d", sum[(size_t)i * c + j]);
}
if (i < r - 1)
printf("\n");
}
free(a);
free(b);
free(sum);
return 0;
}
Problem 15: Find the transpose of a dynamically allocated matrix.
Input: Rows r, columns c, followed by r*c integers.
Output: Print the transposed matrix with c rows and r columns.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r, c;
scanf("%d %d", &r, &c);
size_t count = (size_t)r * (size_t)c;
int *matrix = malloc(count * sizeof *matrix);
if (matrix == NULL)
return 1;
for (size_t i = 0; i < count; i++)
scanf("%d", &matrix[i]);
for (int j = 0; j < c; j++)
{
for (int i = 0; i < r; i++)
{
if (i > 0)
printf(" ");
printf("%d", matrix[(size_t)i * c + j]);
}
if (j < c - 1)
printf("\n");
}
free(matrix);
return 0;
}
Problem 16: Demonstrate the difference between malloc() and calloc() without reading uninitialized malloc memory.
Input: One positive integer n.
Output: Print "malloc needs initialization" and whether all calloc values begin as zero.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
int *a = malloc((size_t)n * sizeof *a);
int *b = calloc((size_t)n, sizeof *b);
if (a == NULL || b == NULL)
{
free(a);
free(b);
return 1;
}
int allZero = 1;
for (int i = 0; i < n; i++)
{
a[i] = i + 1;
if (b[i] != 0)
allZero = 0;
}
printf("malloc needs initialization\n");
printf("calloc zero = %s", allZero ? "Yes" : "No");
free(a);
free(b);
return 0;
}
Problem 17: Write a program that validates the requested array size and checks malloc() before use.
Input: One integer n.
Output: Print "Allocated" for an accepted request or "Request Rejected" for an unsafe request.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
long long n;
scanf("%lld", &n);
if (n <= 0 || n > 1000000)
{
printf("Request Rejected");
return 0;
}
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
{
printf("Allocation Failed");
return 0;
}
printf("Allocated");
free(arr);
return 0;
}
Problem 18: Demonstrate realloc() using a temporary pointer so the original allocation is preserved if resizing fails.
Input: Initial size n, n integers, and new size m where m >= n, followed by new values.
Output: Print the resized array.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, m;
scanf("%d", &n);
int *arr = malloc((size_t)n * sizeof *arr);
if (arr == NULL)
return 1;
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
scanf("%d", &m);
int *temp = realloc(arr, (size_t)m * sizeof *arr);
if (temp == NULL)
{
free(arr);
return 1;
}
arr = temp;
for (int i = n; i < m; i++)
scanf("%d", &arr[i]);
for (int i = 0; i < m; i++)
{
if (i > 0)
printf(" ");
printf("%d", arr[i]);
}
free(arr);
return 0;
}
Problem 19: Demonstrate how a memory leak could occur and show the correct prevention pattern.
Input: One integer.
Output: Print the stored value and "Memory Released".
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
int main()
{
int value;
scanf("%d", &value);
int *p = malloc(sizeof *p);
if (p == NULL)
return 1;
*p = value;
printf("%d\n", *p);
/*
If p were overwritten here before free(p),
the allocation could become unreachable and leak.
*/
free(p);
p = NULL;
printf("Memory Released");
return 0;
}
Problem 20: Create a dynamic Student Record Management System using an array of structures.
Input: n student records (roll, one-word name, marks), then a target roll number.
Output: Print all records, then print the matching student's name and marks or Not Found.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
#include <stdlib.h>
struct Student
{
int roll;
char name[30];
float marks;
};
int main()
{
int n, target;
scanf("%d", &n);
struct Student *students = malloc((size_t)n * sizeof *students);
if (students == NULL)
return 1;
for (int i = 0; i < n; i++)
scanf("%d %29s %f", &students[i].roll, students[i].name, &students[i].marks);
for (int i = 0; i < n; i++)
printf("%d %s %.1f\n", students[i].roll, students[i].name, students[i].marks);
scanf("%d", &target);
for (int i = 0; i < n; i++)
{
if (students[i].roll == target)
{
printf("Found: %s %.1f", students[i].name, students[i].marks);
free(students);
return 0;
}
}
printf("Not Found");
free(students);
return 0;
}
17.35 Key Takeaway
malloc() โ Allocate memory
calloc() โ Allocate + zero-initialize bytes
realloc() โ Resize allocation
free() โ Release memory
NULL โ Check allocation failure
Heap โ Common area for dynamic storage
Memory Leak โ Allocated memory not released
Dangling Pointer โ Pointer to expired/freed object
Use-After-Free โ Accessing freed memory
๐ค Dynamic Memory Allocation โ Interview Questions
๐ก Dynamic Memory Allocation โ Placement Tips
- After every important allocation, check whether the returned pointer is
NULLbefore dereferencing it. - Prefer allocation expressions such as
malloc(n * sizeof *arr)so the size stays tied to the pointed-to type. - With
realloc(), use a temporary pointer and update the original pointer only after success. - Match every successful dynamic allocation with a clear ownership plan for exactly one eventual
free(). - After
free(), do not read or write through that pointer. Setting an owning pointer toNULLcan reduce accidental reuse. - In matrix and multi-allocation problems, if a later allocation fails, free every earlier successful allocation before returning.
โ๏ธ Dynamic Memory Allocation โ Extra Practice Questions
- Dynamically allocate an integer array and remove all duplicate values into a new resized array.
- Create a dynamic string array where each student name receives only the memory it needs.
- Allocate a jagged 2D array where each row has a different number of columns.
- Build a dynamic matrix multiplication program with complete allocation-failure cleanup.
- Implement a growing integer list that doubles its capacity with
realloc()when full. - Create a dynamic structure containing its own dynamically allocated string member and write a cleanup function for it.