Search code examples
cvalgrind

Having trouble with memory leak


I am trying to generate a Fibonacci sequence by allocating space for 2 elements, so I need my array a[0] and a[1] to be constantly updated until it outputs 89 as the final number.

This is my code:

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

void fib2(int* a);

int main()
{
  int *pointer;

  //allocates space for 2 elements for pointer
  pointer = (int*)malloc(2 * sizeof(int*));

  //prints first two fibonacci values
  printf("0 1 ");

  //calls fib2 func and apsses pointer into it
  fib2(pointer);

  //frees pointer memory
  free(pointer);

  printf("\n");

  return 0;
}

//generates fibonacci sequence
void fib2(int* a)
{
  int i;

  //allocates space for 2 elements
  a = (int*)malloc(2 * sizeof(int*));
  //initial fibonacci array initialized
  a[0] = 0;
  a[1] = 1;

  //generates and calculates fibonacci sequence and prints
  for(i = 2; i < 12; i++)
  {
    a[i] = a[i - 1] + a[i - 2];
    printf("%d ", a[i]);

  }

}

I tried freeing of a[] by doing free(a); but it outputs to the console like this

enter image description here

**edit this is the valgrind output enter image description here


Solution

  • There are a number of problems.

    Problem 1 Wrong malloc

    int *pointer;
    
    //allocates space for 2 elements for pointer
    pointer = (int*)malloc(2 * sizeof(int*));
                               ^^^^^^^^^^^^
    

    The sizeof should be sizeof(int) as you want to allocate space for a number (2) int. Besides that you don't need the cast. A better way to write this is:

    pointer = malloc(2 * sizeof *pointer);
    

    Problem 2 You never use pointer for any thing

    You do pass its value to fib2 so that its value goes into variable a. However, immediately after you do:

    a = (int*)malloc(2 * sizeof(int*));  // also sizeof wrong again
    

    so you actually overwrite whatever value that passed. Your call of fib2 could just as well be:

    fib2(NULL);
    

    In other words: Don't do malloc both in main and in fib2. Select one place.

    Problem 3 The memory in malloc'ed in fib2 are never free'ed

    Your current code leaks memory because fib2 doesn't end with code like: free(a);

    Problem 4 You allocate too little memory

    Obviously you want 12 elements in the integer array but you only allocate ! Change code to be:

    a = malloc(12 * sizeof *a);
    

    Putting things together it could look:

    #include <stdio.h>
    #include <stdlib.h>
    
    void fib2(int* a, int n);
    
    #define NUMBERS_TO_CALCULATE 12
    
    int main()
    {
      int *pointer;
    
      //allocates space for NUMBERS_TO_CALCULATE elements for pointer
      pointer = malloc(NUMBERS_TO_CALCULATE * sizeof *pointer);
      if (pointer == NULL) exit(1);
    
      //calls fib2 func and apsses pointer into it
      fib2(pointer, NUMBERS_TO_CALCULATE);
    
      // ... use pointer for other things ...
    
      //frees pointer memory
      free(pointer);
    
      return 0;
    }
    
    //generates fibonacci sequence
    void fib2(int* a, int n)
    {
      int i;
    
      if (n < 2) return;
    
      //initial fibonacci array initialized
      a[0] = 0;
      a[1] = 1;
    
      //prints first two fibonacci values
      printf("0 1 ");
    
    
      //generates and calculates fibonacci sequence and prints
      for(i = 2; i < n; i++)
      {
        a[i] = a[i - 1] + a[i - 2];
        printf("%d ", a[i]);
      }
    
      printf("\n");    
    }
    

    Note: If you don't want to use pointer for other things in main, I'll suggest that you move the malloc and free into fib2

    Edit based on comments from OP

    In comments OP tells about a number of restriction like:

    1. Must use malloc

    2. Only allowed to malloc 2 integers (I assume this also means that local variables are not allowed in fib2)

    3. Function prototype must be void fib2(int* a)

    4. Must print values less or equal 89

    With those restrictions the program could look:

    #include <stdio.h>
    #include <stdlib.h>
    
    void fib2(int* a);
    
    int main()
    {
      int *pointer;
    
      //allocates space for 2 integer elements for pointer
      pointer = malloc(2 * sizeof *pointer);
      if (pointer == NULL) exit(1);
    
      //initialize fibonacci start values
      pointer[0] = 0;
      pointer[1] = 1;
    
      //calls fib2 func and apsses pointer into it
      fib2(pointer);
    
      //frees pointer memory
      free(pointer);
    
      return 0;
    }
    
    //generates fibonacci sequence
    void fib2(int* a)
    {
      //prints first two fibonacci values
      printf("%d %d ", a[0], a[1]);
    
    
      //generates and calculates fibonacci sequence and prints
      while(a[1] < 89)
      {
        a[1] = a[1] + a[0];   // Calculate next number and save in a[1]
        printf("%d ", a[1]);  // Print it
        a[0] = a[1] - a[0];   // Calculate the number for a[0]
      }
    
      printf("\n");
    }