Memory Management in C



One of the important characteristics of C is that the compiler manages how the memory is allocated to the variables declared in the code. Once the compiler allocates the required bytes of memory, it cannot be changed during the runtime.

The compiler employs static memory allocation approach. However, there are times where you may need to allocate the memory on demand, during the runtime. Read this chapter to understand how dynamic memory management works in C.

Functions for Dynamic Memory Management in C

The C programming language provides several functions for dynamic memory allocation and management. These functions can be found in the <stdlib.h> header file.

Function Description
void *calloc(int num, int size); This function allocates an array of num elements each of which size in bytes will be size.
void free(void *address); This function releases a block of memory block specified by address.
void *malloc(size_t size); This function allocates an array of num bytes and leave them uninitialized.
void *realloc(void *address, int newsize); This function re-allocates memory extending it up to newsize.

Allocating Memory Dynamically

If you are aware of the size of an array, then it is easy and you can define it as an array. For example, if you need to store the name of a person, then you can safely define an array to hold a maximum of 100 characters (assuming that a name wouldn't contain more than 100 characters). So, you can define an array as follows −

char name[100];

This is an example of static memory allocation. Now let us consider a situation where you have no idea about the length of the text you need to store, for example, you want to store a detailed description about a topic. In such a case, if the content is less than the allocated size, the allocated memory is wasted during the program’s execution.

On the other hand, if the size required is more than the allocated memory size, it may lead to unpredictable behaviour, including causing the data to be corrupted, as the size of the array cannot be dynamically altered.

It is in these kind of situations you need to use the dynamic memory allocation methods as described in this chapter.

The malloc() Function

This function is defined in the stdlib.h header file. It allocates a block memory of the required size and returns a void pointer.

void *malloc (size)

The size parameter refers to the block of memory in bytes. To allocate a memory required for a specified data type, you need to use the typecasting operator.

For example, the following snippet allocates the memory required to store an int type −

int *ptr;
ptr = (int *) malloc (sizeof (int));

Here we need to define a pointer to character without defining how much memory is required and later, based on requirement, we can allocate memory.

Example

The following example uses the malloc() function to allocate the required memory to store a string (instead of declaring a char array of a fixed size) −

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

int main() {

   char *name;
   name = (char *) malloc(strlen("TutorialsPoint"));
   strcpy(name, "TutorialsPoint");

   if(name  == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
   }
}

Output

When the above code is compiled and executed, it produces the following output −

Name = TutorialsPoint

The calloc() Function

The calloc() function (stands for contiguous allocation) allocates the requested memory and returns a pointer to it.

void *calloc(n, size);

Here, "n" is the number of elements to be allocated and "size" is the byte-size of each element.

The following snippet allocates the memory required to store 10 int types −

int *ptr;
ptr = (int *) calloc(25, sizeof(int));

Example

Let's rewrite the above program using the calloc() function. All that you need to do is replace malloc with calloc

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

int main() {

   char *name;
   name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char));
   strcpy(name, "TutorialsPoint");

   if(name  == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
   }
}

So you have complete control and you can pass any size value while allocating memory, unlike arrays where once the size is defined, you cannot change it.

Resizing and Releasing the Memory

When your program comes out, the operating system automatically releases all the memory allocated by your program. However, it is a good practice to release the allocated memory explicitly by calling the free() function, when you are not in need of using the allocated memory anymore.

In this section, we will highlight the use of two functions, realloc() and free(), that you can use to resize and release the allocated memory.

The realloc() Function

The realloc() (re-allocation) function in C is used to dynamically change the memory allocation of a previously allocated memory. You can increase or decrease the size of an allocated memory block by calling the realloc() function.

The prototype of using the realloc() function is like this −

void *realloc(*ptr, size);

Here, the first parameter "ptr" is the pointer to a memory block previously allocated with malloc, calloc or realloc to be reallocated. If this is NULL, a new block is allocated and a pointer to it is returned by the function.

The second parameter "size" is the new size for the memory block, in bytes. If it is "0" and ptr points to an existing block of memory, the memory block pointed by ptr is deallocated and a NULL pointer is returned.

Example

The following example demonstrates how you can use the realloc() function in a C program −

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

int main() {

   char *name;
   name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char));
   strcpy(name, "TutorialsPoint");

   name = (char *) realloc(name, strlen(" India Private Limited"));
   strcat(name, " India Private Limited");


   if(name == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
   }
}

Output

When the above code is compiled and executed, it produces the following output −

Name = TutorialsPoint India Private Limited

The free() Function

The free() function in C is used to dynamically de-allocate the memory allocated using functions such as malloc() and calloc(), since it is not freed on their own.

In C programming, any reference to unused memory creates a garbage deposition, which may lead to problems like program crashing. Hence, it is wise to use the free() function to perform a manual cleaning operation of the allocated memory.

Here is the prototype to use the free() function −

void free(void *ptr);

Where ptr is the pointer to the block of memory previously allocated.

Example

The following example demonstrates how you can use the free() function in a C program −

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

int main() {

   char *name;
   name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char));
   strcpy(name, "TutorialsPoint");

   if(name  == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
      free(name);
   }
}

Output

At the end of the code, the memory allocated to the char * pointer is de-allocated.

Name = TutorialsPoint India Private Limited
Advertisements