0
votes

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);
   }

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

2
len = max - min + 1; --> len = 1L + max - min; to avoid int overflow when long is wider. Better to use size_t len and (size_t)1. - chux - Reinstate Monica
That assumes long int is is larger than int, so it's not portable code, but it will work on the OP's system. - ikegami
Tried both, neither worked, sorry - Raphael Rakhimov
@RaphaelRakhimov: What exactly do you mean by "neither worked"? Did both give you a segmentation fault? - Andreas Wenzel
First I tried 1L, doesn't work. Then I tried with size_t len and (size_t)1 - doesn't work too. - Raphael Rakhimov

2 Answers

1
votes

int overflow with max - min + 1;

Use wider math for size calculations.

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 || 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;
}
0
votes

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.

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).

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;