Lesson 11.3. Dynamic memory allocation

Memory allocation

Suppose we want to write a program that loads a text from a file. We can't know a priori how big the text will be. This is a problem for the declaration of the string that will contain this text. The solution to this problem is dynamic allocation. If we declare a string of 999 characters, this size will be fixed at compile time and immutable. This becomes a problem if the file contains 2000 characters.

char text[1000];

The solution is to declare a character pointer, then allocate the necessary memory on demand:

char * text;
text = malloc(1000 * sizeof(char));

Malloc

malloc() is a function in the standard C library stdlib.h. malloc stands for Memory ALLOCation. This function allocates (or reserves) a block of memory of a defined size in bytes.

#include <stdlib.h>
void* malloc(size_t size)

The malloc() function allocates a block of memory of size bytes and returns the address of the beginning of the block. If malloc() fails to allocate the memory, the function returns a null pointer (0). Note that, as for arrays, the block of memory is necessarily continuous.

The type of the function is void*, which might at first seem paradoxical. In reality, it means that the function returns a pointer without any associated type. It is up to the developer to cast the pointer to the desired type:

// Declare an integer pointer 
int * buffer;

// Allocate 200 integers for the buffer
buffer =(int*)malloc(200 * sizeof(int));

buffer can be used exactly as an array :

buffer[199] = 30;

Free

The free function free (deallocate) previously allocated memory.

void free (void* ptr);

Let's go back to the previous example, when buffer is not used anymore, it is possible to deallocate (free) the memory :

// Dynamically allocate an array of 200 integers
int * buffer;
buffer =(int*)malloc(200 * sizeof(int));

...

// Free the memory used by the array
free (buffer);

A classic mistake when using dynamic allocation is to allocate memory, but forget to free it. The program reserves more and more memory blocks, but does not free them (or only partially). The program ends up using all the available memory and

Here is an example of code that should absolutely be avoided:

char* buffer;
while (1) {
  // Allocate 10Mb
  buffer = (char*)malloc(1e7);
  ...
  // No call to free(buffer);
}

The above code was executed on a PC with 32GB of RAM. It takes less than a minute to crash the computer:

Memory leak during dynamic allocation

Realloc

The realloc function modifies (increase or decrease) the size of a previously allocated block. Here is an example:

float tab*;
// Allocate an array of 100 floats
tab = (float*)malloc(100 * sizeof(float));

...

// Modify the array for 500 cells
tab = (float*)realloc(tab, 500 * sizeof(float));

Note that the realloc() function can change the pointer address if necessary. In this case, the original data will be copied into the new block. If the new block is larger, the excess will contain arbitrary values.

Exercise

Write a program that

How many cells in array: 50
1 4 9 19 8 10 10 9 15 10 2 19 20 4 20 7 3 15 16 16 17 14 12 9 2 5 5 13 1 19 5 0 3 12 17 9 1 7 16 16 15 18 12 14 20 10 20 2 2 15

Test the program with ten billion cells in array :

How many cells in array: 10000000000
Not enough memory.
exit status 1

Quiz

What is the purpose of dynamic allocation?

Check Bravo! Dynamic allocation is used to allocate memory on the fly. Try again...

What does the following code do?

buffer = (int*)malloc(1000);
Check Bravo! The parameter of malloc() is the size in bytes. Try again...

What is a memory leak?

Check Bravo! A memory leak is a continuous allocation of memory without it ever being freed. Try again...

With the realloc() function...

Check Bravo! realloc() is used to increase or decrease a previously dynamically allocated memory space. Try again...

What will happen to the ptr pointer?

ptr = (char*)realloc(ptr, 100);
Check Bravo! During the reallocation, the address of the pointer can be modified. If the reallocation fails, the function returns the NULL pointer. Try again...

See also


Last update : 11/29/2022