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_tfor allocation size and indexingAdd 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);
}
