Dynamic Memory Allocation · Lesson 25 of 35
malloc, calloc and free in C
So far every array had a size fixed when you wrote the program. But often you only know the size at run time: how many students the user enters, how big a file is. Dynamic memory allocation lets you request exactly as much memory as you need from the heap while the program runs – and gives you the job of returning it.
In this lesson
- Stack vs heap
mallocand checking for NULLcallocand how it differsfree, and why every allocation needs one
Stack vs heap
| Stack | Heap | |
|---|---|---|
| Holds | local variables, function calls | memory you request with malloc/calloc/realloc |
| Size | small (often 1–8 MB) | large – most of the free RAM |
| Lifetime | ends when the function returns | until you call free |
| Managed by | the compiler, automatically | you |
| Speed | very fast | slower to allocate |
malloc
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n;
printf("How many students? ");
scanf("%d", &n);
int *marks = malloc((size_t)n * sizeof *marks); // room for n ints on the heap
if (marks == NULL) { // allocation can fail
printf("Out of memory\n");
return 1;
}
int total = 0;
for (int i = 0; i < n; i++) {
marks[i] = 60 + i * 7; // use it like an array
total += marks[i];
}
printf("Marks:");
for (int i = 0; i < n; i++) printf(" %d", marks[i]);
printf("\nAverage: %.2f\n", (double)total / n);
free(marks); // give the memory back
marks = NULL; // avoid a dangling pointer
return 0;
}
How many students? 5 Marks: 60 67 74 81 88 Average: 74.00
The allocation pattern
- Requestp = malloc(count * sizeof *p)
- Checkif (p == NULL) handle the error
- Usep[i] like an array
- Releasefree(p); p = NULL;
malloc(bytes)returns avoid *to uninitialised memory, orNULLif it fails. In C there's no need to cast the result.- Writing
sizeof *marksinstead ofsizeof(int)stays correct even if you later change the pointer's type. - The memory contains garbage until you write to it.
calloc
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 6;
int *votes = calloc((size_t)n, sizeof *votes); // n elements, all set to zero
if (votes == NULL) return 1;
int ballots[] = {2, 4, 2, 0, 5, 2, 4};
for (int i = 0; i < 7; i++) votes[ballots[i]]++;
for (int c = 0; c < n; c++) printf("candidate %d: %d vote(s)\n", c, votes[c]);
free(votes);
return 0;
}
candidate 0: 1 vote(s) candidate 1: 0 vote(s) candidate 2: 3 vote(s) candidate 3: 0 vote(s) candidate 4: 2 vote(s) candidate 5: 1 vote(s)
malloc(size) | calloc(count, size) | |
|---|---|---|
| Arguments | total bytes | number of elements and size of each |
| Initial contents | garbage | all bytes zero |
| Overflow check | you must check count × size yourself | checks count × size for overflow |
| Use when | you'll fill every element anyway | you need zeros (counters, flags) |
Returning heap memory from a function
Unlike a local array, heap memory survives after the function returns – so a function can create data and hand it to the caller, who becomes responsible for freeing it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *make_greeting(const char *name) {
size_t len = strlen("Hello, ") + strlen(name) + strlen("!") + 1; // +1 for '\0'
char *s = malloc(len);
if (s == NULL) return NULL;
snprintf(s, len, "Hello, %s!", name);
return s; // the caller must free this
}
int main(void) {
char *msg = make_greeting("Meera");
if (msg != NULL) {
printf("%s (%zu chars)\n", msg, strlen(msg));
free(msg);
}
return 0;
}
Hello, Meera! (13 chars)
Who frees it?
Every malloc/calloc/realloc needs exactly one matching free. Decide and document who owns each block – "the caller must free the returned string" – just as the standard library documents it for functions like strdup.
Practice
Try it yourself
Read n, allocate n doubles, store the squares of 1…n and print their sum.
Show solution
#include <stdio.h> #include <stdlib.h> int main(void) { int n; printf("n: "); scanf("%d", &n); double *sq = malloc((size_t)n * sizeof *sq); if (sq == NULL) return 1; double sum = 0; for (int i = 0; i < n; i++) { sq[i] = (double)(i + 1) * (i + 1); sum += sq[i]; } printf("sum of squares 1..%d = %.0f\n", n, sum); free(sq); return 0; }n: 10 sum of squares 1..10 = 385
Quick check
What does malloc return when it fails?
NULL.
malloc vs calloc?
malloc takes a byte count and leaves memory uninitialised; calloc takes count and size and zeroes the memory.
When is heap memory released?
Only when you call free (or the program ends).
Summary
- The heap gives you memory sized at run time that lives until you free it.
- malloc gives uninitialised memory, calloc gives zeroed memory; always check for NULL.
- Every allocation needs one free; set the pointer to NULL afterwards.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.