ProgramGuru

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.

  1. Explain

    Check allocation, initialize elements and release owned storage.

  2. Trace

    Allocate two marks, initialize both to 45 and print their sum.

  3. Apply

    Identify missing cleanup, repeated cleanup and access after cleanup.

Dynamic Memory: follow the data

  1. 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.

  2. 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.

  3. Result

    Last mark: 42

A guided model of this example. The illustration explains the process; run the complete C program to check its output.

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

  1. Read the starting values

    A successful allocation reserves space for three integers.

  2. Perform the operation

    The initialization writes 40, 41 and 42 before the last element is read. free releases the buffer after its final use.

  3. Check the observable result

    Last mark: 42

    Last mark: 42
A guided model of this example. The illustration explains the process; run the complete C program to check its output.

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.

Does malloc initialize a new marks array to zero?
Choose one answer. You can try again.

Answer and explanation

No; initialize its elements before reading them.

Correct. Allocation supplies storage, not defined integer values.

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.

    Next lesson: C File Input, Output and Resource Cleanup →