Home > Software design >  Segmentation fault in malloc()
Segmentation fault in malloc()

Time:09-24

I need to create a function which returns an array ofints. This int array should contain all values between min and max (both included).

  • If min >= max a null pointer should be returned.

The question is why when (min = -2147483468) and (max = 2147483647) and len becomes 4294967296 I get "Segmentation fault". My code:

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

   int *ft_range(int min, int max)
   {
       int         *range;
       long int    len;
       long int    i;

       range = NULL;
       if (min >= max)
           return (NULL);
       len = max - min   1;
       if(!(range = (int *)malloc(sizeof(int) * len)))
           return (NULL);
       i = 0;
       while (min < max)
       {
           range[i] = min;
           min  ;
           i  ;
       }
       range[i] = max;
       return (range);
   }


   int main(void)
   {
       int      max;
       int      min;
       long int     len;
       int      *range;
       long int     i;

       max = 2147483647;
       min = -2147483648;
       if (max != min)
           len = max - min   1;
       else
           len = 0;
       i = 0;
       range = ft_range(min, max);
       while (i < len)
       {
           printf("%d", range[i]);
           i  ;
       }
       free(range);
       return (0);
   }

But if I enter (min = -2147483468) and (max = 2147483646) with (len = 4294967295) it works.

CodePudding user response:

int overflow with max - min 1;

  • Use wider math for size calculations.

  • Use size_t for allocation size and indexing

  • Add more error checks.


int *ft_range(int min, int max) {
  // Add required test explicitly
  if (min >= max) {
    return NULL;
  }

  long long size = 1LL   max - min; // Use long long math
  if (size > SIZE_MAX/sizeof(int) || size < 1) {
    return NULL;
  }
  size_t usize = (size_t)size;

  int *range = malloc(sizeof *range * usize);
  if (range == NULL) {
    return NULL;
  }

  size_t i = 0;
  while (min < max) {
    range[i] = min;
    min  ;
    i  ;
  }
  range[i] = max;
  return range;
}

CodePudding user response:

min and max are type int, which is only guaranteed to be 16 bits signed (-32768, 32767), although the compiler may choose to use more bits to store the values. Therefore, if you were to expect values ranging (-2147483468, 2147483647), these should be of type long int. The program may or may not be be truncating some of the bits when you supply (-2147483468, 2147483647) or (-2147483468, 2147483646) as inputs. This would also apply to the type for range.

Secondly, variable len is long int which is only guaranteed to be 32 bits signed (-2147483468, 2147483647). Since you want to be able to store value 4294967296, this will need to be either long long int or long long unsigned int. Even long unsigned int will only have a range of (0, 4294967295). This would also apply to i.

Additionally, the statement len = max - min 1;, will need to include a type cast to long long int to avoid overflow when performing the arithmetic. You can do it by adding (long long int) this way: len = (long long int)max - min 1;; or if you want to be more explicit: len = ((long long int)max - (long long int)min) 1LL;

To summarize:

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

   int *ft_range(long int min, long int max)
   {
       long int         *range;
       long long int    len;
       long long int    i;

       range = NULL;
       if (min >= max)
           return (NULL);
       len = (long long int)max - min   1;
       if(!(range = (int *)malloc(sizeof(int) * len)))
           return (NULL);
       i = 0;
       while (min < max)
       {
           range[i] = min;
           min  ;
           i  ;
       }
       range[i] = max;
       return (range);
   }

Side note: Range (-2147483468, 2147483647) is going to require around 16 GB of memory to be allocated, so I hope that you are ready for that.

CodePudding user response:

I solved the problem by using len and i as long long int, added long long int this way:

len = (long long int)max - min   1;

Also I forgot to check if malloc returns NULL in main() function.

This is the correct version:

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

    int *ft_range(int min, int max)
    {
        int             *range;
        long long int   len;
        long long int   i;

        range = NULL;
        if (min >= max)
            return (NULL);
        len = (long long int)max - min   1;
        if(!(range = (int *)malloc(sizeof(int) * len)))
            return (NULL);
        i = 0;
        while (min < max)
        {
            range[i] = min;
            min  ;
            i  ;
        }
        range[i] = max;
        return (range);
    }

    int main(void)
    {
        int             *range;
        int             max;
        int             min;
        long long int   len;
        long long int   i;

        max = 2147483647;
        min = -2147483648;
        len = 0;
        if (max != min)
            len = (long long int)max - min   1;
        i = 0;
        if(!ft_range(min, max))
            return (0);
        range = ft_range(min, max);
        while (i < len)
        {
            printf("%d", range[i]);
            i  ;
        }
            free(range);
            return (0);
    }
  • Related