C Dynamic Memory, Allocation Failure and Ownership
C Dynamic Memory, Allocation Failure and Ownership
The number of student marks is known only while the program runs. An allocated buffer can fit that count, but it needs a clear owner and a reliable release path.
malloc requests storage and returns a pointer or null on failure. That storage is not initialized. The program must stay within the allocation, manage its lifetime and free it exactly once when ownership ends.
Explain
Check allocation, initialize elements and release owned storage.
Trace
Allocate two marks, initialize both to 45 and print their sum.
Apply
Identify missing cleanup, repeated cleanup and access after cleanup.
Dynamic Memory: follow the data
Start
The number of student marks is known only while the program runs. An allocated buffer can fit that count, but it needs a clear owner and a reliable release path.
Operation
malloc requests storage and returns a pointer or null on failure. That storage is not initialized. The program must stay within the allocation, manage its lifetime and free it exactly once when ownership ends.
Result
Last mark: 42
Understand the operation
Use sizeof *marks to allocate according to the pointed-to type. Before multiplying a general count by an element size, verify that the multiplication can be represented in size_t. The demonstration’s fixed count of three is safely bounded.
After checking malloc’s result, initialize every element that will be read. free ends the allocated storage’s lifetime. Setting one local pointer to NULL afterward does not repair other aliases that still point to the freed allocation.
Read the complete C program
This complete C17 program uses a small school example. Read declarations before the statements that use their values. Each printf format describes how the corresponding value is written to standard output.
C17 · complete program
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t count = 3;
int *marks = malloc(count * sizeof *marks);
if (marks == NULL) { fputs("Allocation failed\n", stderr); return 1; }
for (size_t i = 0; i < count; i++) marks[i] = 40 + (int)i;
printf("Last mark: %d\n", marks[2]);
free(marks);
return 0;
}
Expected output
Last mark: 42
Run in C compiler →Follow the values through the code
C17 · code used in this explanation
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t count = 3;
int *marks = malloc(count * sizeof *marks);
if (marks == NULL) { fputs("Allocation failed\n", stderr); return 1; }
for (size_t i = 0; i < count; i++) marks[i] = 40 + (int)i;
printf("Last mark: %d\n", marks[2]);
free(marks);
return 0;
}
A successful allocation reserves space for three integers.
The initialization writes 40, 41 and 42 before the last element is read. free releases the buffer after its final use.
Follow the worked calculation
Read the starting values
A successful allocation reserves space for three integers.
Perform the operation
The initialization writes 40, 41 and 42 before the last element is read. free releases the buffer after its final use.
Check the observable result
Last mark: 42
Last mark: 42
Try a small variation
C17 · code used in this explanation
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t count = 3;
int *marks = malloc(count * sizeof *marks);
if (marks == NULL) { fputs("Allocation failed\n", stderr); return 1; }
for (size_t i = 0; i < count; i++) marks[i] = 40 + (int)i;
printf("Last mark: %d\n", marks[2]);
free(marks);
return 0;
}
Allocate two marks, initialize both to 45 and print their sum.
Worked answer
Both read elements were initialized and the program releases the allocation after computing 90. The output assumes successful allocation; real failure is handled before any access.
C17 · complete program
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *marks = malloc(2 * sizeof *marks);
if (marks == NULL) return 1;
marks[0] = 45; marks[1] = 45;
printf("Total: %d\n", marks[0] + marks[1]);
free(marks);
return 0;
}
Expected output
Total: 90
Run in C compiler →Recognize the important boundaries
Do not use a pointer after free, free the same allocation twice or free an automatic array. These are different lifetime errors, not interchangeable cleanup techniques.
For realloc, preserve the original pointer until success; a failed nonzero-size request leaves the original allocation available. New storage after growth must be initialized before reading.
Check your understanding
Choose the answer, then compare the reasoning for every option.
Use the idea independently
malloc requests storage and returns a pointer or null on failure. That storage is not initialized. The program must stay within the allocation, manage its lifetime and free it exactly once when ownership ends.
Continue with resource cleanup for files.
Language reference: WG14 C11 committee draft. These examples use the C17-compatible subset of the explained language features.
Reaching the recap and completing the quizzes are separate milestones.