This blog is under construction

Saturday, 2 November 2013

Dynamic memory allocation using pointers

What is dynamic memory allocation?
Dynamic memory allocation is the method of allocating a block of memory dynamically during the run time of a program.  And the dynamically allocated block can be freed if it is not needed.  Below are the APIs available in C library to perform dynamic memory allocation.
  • malloc()
  • calloc()
  • realloc()
Below is the API available in C standard library which is used to free the dynamically allocated block.
  • free()

Difference between heap and stack?

Whenever we do dynamic memory allocation at the run time of a program, the memory block is reserved from the area called heap.  Whereas, the memory for local variables and function arguments are allocated during the compile time itself.  And the memory area reserved for local variables and function arguments is called stack.



Difference between dynamic memory allocation and static memory allocation:
The process of allocating memory dynamically at run time is called dynamic memory allocation.  Standard library functions like malloc(), calloc() and realloc() are used to perform dynamic memory allocation.  Whereas, the process of allocating memory during the compile time is called static memory allocation.  Memory area used for static memory allocation is stack.  So, the memory for local variables and arguments are reserved from stack.  Whereas, the memory area used for dynamic memory allocation is heap.  And the dynamic memory allocation can be performed using pointers.  The space allocated for local variables and arguments are freed once the execution of the function gets over.  But, the dynamically allocated block(heaps) are controlled by users.  User has to explicitly free the dynamically allocated memory block.  If not, it might result to memory leaks.


Advantages and disadvantages of dynamic memory allocation:

Advantages:
  • Dynamic memory allocation allows user to allocate memory at run time
  • The memory area used for dynamic memory allocation is heap.  And this heap is accessible from any part of the program(scope is unlimited).
  • It allows user to free the unused dynamically allocated memory.

Disadvantages:
  • Memory leaks will occur, if user misses to free the dynamically allocated memory.
  • Fragmentation is an another disadvantage with dynamic memory allocation. Consider, we have 1MB of free memory in heap, but the memory blocks were not contiguous.  And if user request 1MB memory block, then he can't get the requested block since the available free memory were not contiguous.

Syntax for dynamic memory allocation:
Below are the few syntaxes to perform dynamic memory allocation
     ptr = (type *)malloc(size);
     ptr - pointer variable
     type - data type
     size - number of bytes to be allocated

     ptr = (type *)calloc(n, size);
     ptr - pointer variable
     type - data type
     n - number of block to be allocated
     size - number of bytes in each block

     new = realloc(ptr, size);
     ptr - pointer to an existing block
     new - pointer to reallocated block
     size - number of bytes to be allocated


Difference between malloc and calloc
malloc() function: 
Below is the prototype of malloc() function.
     void * malloc(size_t); 

malloc() is a general purpose function which is used to dynamically allocate memory for any type of data at run time.  This function allocates the requested byte of memory and returns the address of the first byte of the allocated memory block.  Below is an example for dynamic memory allocation using malloc().

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

Size of an integer is 4 bytes.  So, we have requested 16 bytes(size of 4 integers) of memory. And malloc() function returns the address of the first byte of the allocated block. The type casting(int *) is used to convert the address returned by malloc() to the type "pointer to integer".


calloc() function:  
Below is the prototype of calloc() function.
     void *calloc(size_t nmemb, size_t size);

calloc() is also a general purpose function which is used to dynamically allocate memory in multiple blocks of same size.  For calloc(), we need to provide two arguments.  One is number of elements and the other one is the size of each element.  This function also allocates the requested memory and returns the address of the first byte of the allocated block.

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

Here, number of elements(4) and size of integer(4 bytes) are passed as arguments.  So, calloc() function will allocate a 16 byte block and returns the address of the first byte of the allocated block.  Apart from that, calloc() writes 0 in all bytes of the allocated block. So, memory block allocated by calloc() won't have any junk values.  Whereas, the memory block allocated by malloc() will be uninitialized.  So, its users responsibility to initialize the memory block allocated using malloc().

realloc() function:
Below is the prototype for realloc() function.
     void *realloc(void *ptr, size_t size);

realloc() function is used to modify the size of the memory block pointed by pointer ptr to size bytes.  The old contents in the existing memory block remains unchanged.  Whereas, the newly allocated memory region will be uninitialized.

     int *ptr = (int *)realloc(NULL, 40);

The above statement is equivalent to malloc(40).  In case if the size is 0 and pointer ptr is not NULL, then the call is equivalent to free(ptr);

     int *ptr = (int *)realloc(ptr, 0);

So, the above statement is equivalent to free(ptr).

free() function:
free() function is used to deallocate the memory space allocated using malloc(), calloc() or realloc() function.  Below is the prototype for free() function.
     void free(void *ptr);


Dynamic memory allocation using malloc/calloc /realloc:
Below is an example program that illustrates dynamic memory allocation using malloc, calloc or realloc


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

  int main() {
        int i, n, ch, *mptr, *cptr;

        /* getting number of inputs from user */
        printf("Enter number of inputs:");
        scanf("%d", &n);

        /* dynamic memory allocation using malloc, calloc */
        mptr = (int *) malloc(sizeof(int) * n);
        cptr = (int *) calloc(n, sizeof(int));

        /* filling the values in mptr and cptr array */
        for (i = 0; i < n; i++) {
                mptr[i] = 100 + (i * 100);
                cptr[i] = 50 + (i * 50);
        }

        printf("Do wanna perform deallocation(0/1):");
        scanf("%d", &ch);

        if (!ch) {
                return 0;
        }

        /* reallocating the memory */
        mptr = realloc(mptr, (n + 3) * sizeof(int));

        /* filling data in uninitialized memory */
        for (i = n; i < (n + 3); i++) {
                mptr[i] =  100 + (i * 100);
        }
        /* printing the outputs */
        printf("\nPrinting the values in mptr:\n");
        for (i = 0; i < (n + 3); i++) {
                printf("mptr[%d]: %d\n", i, mptr[i]);
        }

        printf("\nPrinting the values in cptr:\n");
        for (i = 0; i < n; i++) {
                printf("cptr[%d]: %d\n", i, cptr[i]);
        }

        /* freeing dynamically allocated memory blocks */
        free(mptr);
        free(cptr);
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Enter number of inputs:2
  Do wanna perform deallocation(0/1):1

  Printing the values in mptr:
  mptr[0]: 100
  mptr[1]: 200
  mptr[2]: 300
  mptr[3]: 400
  mptr[4]: 500

  Printing the values in cptr:
  cptr[0]: 50
  cptr[1]: 100



Dynamic memory allocation for an array in c:
Below statement allocates memory for an array of 100 integers.
     int *ptr = (int *) malloc(100 * sizeof(int));

Above statement is almost equivalent to the below declaration.
     int arr[100];

Let us see how to dynamically allocate memory for an array of 100 integers using calloc() and realloc().
     int *ptr = (int *)calloc(100, sizeof(int));
     int *ptr = (int *)realloc(NULL, sizeof(int) * 100));


Dynamic memory allocation for two dimensional arrays:
Consider a two dimensional array with 3 rows and 3 columns.
     int array[3][3];

Below statements explains how to dynamically allocate memory for two dimensional array with 3 rows and 3 columns
     int i, **ptr;
     ptr = (int **)malloc(3 * sizeof(int));
     for (i = 0; i < 3; i++)
          ptr[i] = (int *)malloc(3 *sizeof(int));

Dynamic memory allocation for double pointer using calloc:
Below is the procedure to perform dynamic memory allocation for double pointer.
     int i, **ptr;
     ptr = (int **)calloc(3, sizeof(int));
     for (i = 0; i < 3; i++) {
    ptr[i] = (int *)calloc(3, sizeof(int));
     }

The above statement is equivalent to
     int arr[3][3];


Dynamic memory allocation for structures
Let us see how to perform dynamic memory allocation for a structure.  Below structure has three members: number(integer), val(float) and ch(character).

     struct data {
     int number;
             float val;
          char ch;
     };

     struct data *ptr = (struct data *)malloc(sizeof(struct data));

So, we have dynamically allocated memory for a structure.  Let us try to assign value for structure members.
     ptr->number = 10;
     ptr->val = 20.33;
     ptr->ch = 'z';

Dynamic memory allocation for 3d array/triple pointer:
Consider the below three dimensional array.
     int array[4][3][2];

Below statements explains how to dynamically allocate memory for a three dimensional array which is similar to the above one.
     int i, j, ***ptr;

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

     for (i = 0; i < 4; i++)
          ptr[i] = (int **)malloc(3 *sizeof(int));

     for (i = 0; i < 4; i++) {
          for (j = 0; j < 3; j++) {
               ptr[i][j] = (int *)malloc(2 * sizeof(int));
          }
     }

No comments:

Post a Comment