Memory allocation on the fly can be done using the malloc function call. This is usually done when a dynamic amount of memory is required that cannot be decided prior to program execution. Malloc is the way to achieve this. The programmer must be diligent in allocating the correct amount of memory, type cast it appropriately, and remember to free it after usage. Otherwise this memory may be leaked during execution.
This article will outline the usage of malloc, how to free that memory after the fact, and how to avoid dangling pointers and invalid memory access.
How Do I Allocate Memory?
Most people are familiar with allocating an array of 10 integers:
int data[10];
But what if we actually need 12 integers or 15, what then? This is where malloc comes in. Its defintion is:
void *malloc(size_t size);
malloc return a void *, meaning we can cast this memory to whatever type we need. It takes a size as its argument, in this case the number of bytes we need. Here is an example of allocating 12 integers. If you want more examples of using fprintf follow this link.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *data_ptr;
data_ptr = (int *)malloc(sizeof(int) * 12);
if(data_ptr == NULL){
fprintf(stderr, "Could not allocate memory.\n");
return -1;
}
data_ptr[0] = 5;
data_ptr[1] = 3;
fprintf(stdout, "%u\n",data_ptr[0]);
// Cleanup our allocated memory
free(data_ptr);
data_ptr = NULL;
return 0;
}
There a few things to note in this example:
- Malloc returns NULL on error. This must be checked! Do not just point randomly.
- I reference our pointer using the same syntax as if I allocated the memory statically.
- During our cleanup I call free. free() returns no error, and takes the pointer in which memory was allocated to.
- I set the pointer to NULL after I free the memory. This ensure no dangling pointer.
Allocating memory can be done for any type required, as behind the scenes you are simply allocating bytes. In the example above we used the sizeof function. This is imperative that we use this function, because in some cases a long is 8 bytes on one system where a long on another system is only 4 bytes. When we use sizeof we let the system tell us how the size of the type, and thus we multiply it by how many of those we need. In our example we needed 12 integers, without having to know the actual byte size behind the scenes.
If you want to do something more complicated, you can try dynamically allocate structures using malloc.