0

I need to create a function which returns an array of ints. 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.

16
  • 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. Commented Sep 23, 2021 at 16:48
  • That assumes long int is is larger than int, so it's not portable code, but it will work on the OP's system. Commented Sep 23, 2021 at 16:49
  • 1
    Are you sure that the segfault is occuring in the code that you are showing us? Please provide a minimal reproducible example (including the function main). Commented Sep 23, 2021 at 17:23
  • 1
    What is your compiler and OS? Also, make every variable long long int. Commented Sep 23, 2021 at 17:37
  • 1
    Replace min = -2147483648; with min = -2147483647 - 1; to avoid UB. Commented Sep 23, 2021 at 18:21

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Doesn't work. Added a main() function because I suspect there may be a bug in it too
It will not work (malloc will return NULL) if your system is not capable of allocating 16 GB of memory or if size_T is smaller than long long int. Did you confirm that malloc is not returning NULL?
Thank you, applied some of your advices and solved the problem.
1

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

2 Comments

My only allowed function is malloc, sry. Added a main() function because I suspect there may be a bug in it too
@RaphaelRakhimov What other function do you see in this answer?
0

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

1 Comment

When sizeof(int) * len > SIZE_MAX, this code has problems with malloc(sizeof(int) * len) leading to undeifned behavior (UB).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.