C Language | Advanced Features | Dynamic Memory Allocation - malloc(), free()

When the required storage size is not known until runtime, a program must allocate memory dynamically. C provides malloc() to allocate memory and free() to release it.

Allocating Memory at Runtime

The size of a normal array is fixed when it is declared. This is not sufficient for applications such as text editors, because the amount of user data cannot be known at compile time.

The standard library declares malloc() in stdlib.h.

malloc() function

void* malloc(size_t size);

size specifies the number of bytes. The function returns a pointer to the allocated heap memory, or NULL if allocation fails. Always check for NULL before using the pointer.

Code 1

#include <stdio.h>
#include <stdlib.h>
#define ALPHABET_COUNT 26

int main() {
 int iCount;
 char *str = (char *)malloc(ALPHABET_COUNT + 1);
 if (str == NULL) return 1;
 for(iCount = 0 ; iCount < ALPHABET_COUNT ; iCount++)
   str[iCount] = 0x41 + iCount;
 str[iCount] = 0;
 printf("%s\n" , str);
 free(str);
 return 0;
}

This program allocates 27 bytes and prints the alphabet. Never access memory beyond the allocated size. For other types, calculate the required byte count with sizeof, such as sizeof(int) * 4.

Memory allocated with malloc() is not automatically released when a local scope ends. Repeated allocation without release causes a memory leak.

Code 2

#include <stdio.h>
#include <stdlib.h>

int main() {
 while(1) {
   int *iPo = (int *)malloc(sizeof(int) * 0x100000);
   if (iPo == NULL) {
     printf("Memory could not be allocated.\n");
     break;
   }
   printf("iPo = %p\n" , iPo);
 }
 return 0;
}

The lost pointers in this example prevent the allocated blocks from being reused. Long-running programs can eventually exhaust available memory.

free() function

void free(void *memblock);

Pass only a pointer returned by an allocation function, and do not release the same pointer twice.

Code 3

#include <stdio.h>
#include <stdlib.h>

int main() {
 while(1) {
   int *iPo = (int *)malloc(sizeof(int) * 0x100000);
   if (iPo == NULL) {
     printf("Memory could not be allocated.\n");
     break;
   }
   printf("iPo = %p\n" , iPo);
   free(iPo);
 }
 return 0;
}

Real programs often allocate and release memory in different functions. Define pointer ownership clearly and decide exactly when each allocated block must be released.