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