Difference Between Malloc and Calloc in C

1. Overview

To allocate memory dynamically in C, we use functions like malloc() and calloc(). Both allocate memory on the heap, but have different initialization behavior. Common use cases of memory allocation in C include arrays or structured data of variable length only known at runtime,  buffers for I/O operations when size is unpredictable, etc.

In this tutorial, we’ll delve into the practical usage of malloc() and calloc() and highlight the difference between the two functions.

2. malloc()

Memory allocation is required for data that’s size is only known at runtime. Programming languages with garbage collectors do that automatically. In C, we need to manually allocate and free memory.

The malloc() function allocates a block of uninitialized memory on the heap. We specify the number of bytes needed, malloc() handles requesting the memory from the OS.

If we failed to initialize the memory space and use it, it may contain garbage values that can introduce bugs to our code.

2.1. Basic Usage

To use malloc(), we need to add the stdlib.h header to the source code.

Here’s a sample code that allocates memory to implement copy:

char *input = malloc(sizeof(char));
printf("Enter a word for me to copy: ");
scanf("%s", input);
char *t = malloc(strlen(input) + 1);

for (int i = 0, n = strlen(input) + 1; i < n; i++) {
    t[i] = input[i];
}
t[0] = toupper(t[0]);
printf("original: %s\n", input);
printf("copied: %s\n", t);
free(t);
free(input);

In the code above, we allocate a chunk of memory to the input and also to the variable that will store the duplicate. Furthermore, we iterate through the input which is an array of characters, and copied it to t.

Since we allocate memory to the input, it can grow within the size of the memory allocated.

Additionally, the allocated memories were freed to avoid memory leakage.

2.2. Garbage Values

In this section, we’ll examine a simple program to fill the heap with random junk data and try to output values of memory allocated using malloc().

Firstly, let’s fill up the heap with junk data:

int size = 0;
int *junk = 0;
srand( time(0) );
for (int i = 0; i < 1000; i++) {
    size = rand() % 16000;
    junk = malloc( size * sizeof(int) );
    for (int j = 0; j < size; j++){
      junk[j] = rand();
    }
    free(junk);
}

Here, we create an integer pointer and allocate some chunks of memory. Then, we fill up the memory with some random values.

Next, let’s allocate memory to a pointer integer without initializing it:

 int *array;
 array = malloc( 1000 * sizeof(int) );
 for (int i = 0; i < 1000; i++)
    printf("%d", array[i]);
 free(array);
 printf("\n");

In the code above, we create a new variable with dynamic memory. The variable isn’t initialized, let’s see the output of the code:

16043843511457148993718195211284436095694728317212104001959714

These are garbage values on the heap. If we don’t know that there’s such value on the heap, it could through bug to our code and impact performance.

3. calloc()

calloc() allocates memory just like malloc(), but also initializes it to zero. This avoids unintended values in the allocated memory. The initialization does carry a performance cost compared to malloc().

In the last section, we saw a code with garbage values. Let’s improve the code by using calloc() instead of malloc():

int *array;
array = calloc( 1000, sizeof(int) );
for (int i = 0; i < 1000; i++)
    printf("%d", array[i]);
free(array);
printf("\n");

By default, calloc() will initialize the memory block to zero preventing garbage values. Let’s see the output of the improved code:

000000000000000000000000000000000

Despite having some values as junk on the heap, calloc() initializes the values in the memory chunk to zero.

4. malloc() vs calloc()

malloc() returns uninitialized memory which comes with a higher risk of bugs. Although, malloc() is faster than calloc().

On the other hand, calloc() returns initialized memory which makes its behavior more predictable compare to calloc()

5. Conclusion

In this article, we learn the basics of malloc() and calloc() and their use case. Dynamic memory allocation with malloc() and calloc() allows C programs to efficiently manage memory usage at runtime. malloc() is faster but risks bugs if misused while calloc() offers safety through initialization.

The complete source code for the examples is available on GitHub.