malloc() 中的分段错误

Segmentation fault in malloc()

我需要创建一个 returns 整数数组的函数。此 int 数组应包含最小值和最大值之间的所有值(均包含在内)。

问题是,为什么当 min = -2147483468max = 2147483647(并且 len 变为 4294967296)时,我得到“分段错误”?

我的代码:

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

但是,如果我输入 min = -2147483468max = 2147483646 以及 len = 4294967295 就可以了。

int 溢出 max - min + 1;

  • 使用更广泛的数学计算尺寸。

  • 使用size_t分配大小和索引

  • 添加更多错误检查。


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

minmax 是类型 int,它只保证是 16 位有符号的(-32768、32767),尽管编译器可能会选择使用更多位来存储值。因此,如果您希望值的范围为 (-2147483468, 2147483647),则这些值的类型应为 long int。当您提供 (-2147483468, 2147483647) 或 (-2147483468, 2147483646) 作为输入时,程序可能会或可能不会截断某些位。这也适用于 range.

的类型

其次,变量lenlong int,它只保证是32位有符号的(-2147483468、2147483647)。由于您希望能够存储值 4294967296,因此这需要是 long long intlong long unsigned int。即使 long unsigned int 的范围也只有 (0, 4294967295)。这也适用于 i.

此外,语句 len = max - min + 1; 需要包含一个类型转换为 long long int 以避免在执行算术运算时溢出。您可以通过这样添加 (long long int) 来实现:len = (long long int)max - min + 1;;或者如果你想更明确:len = ((long long int)max - (long long int)min) + 1LL;

总结一下:

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

旁注:范围 (-2147483468, 2147483647) 将需要分配大约 16 GB 的内存,因此我希望您已为此做好准备。

我通过使用 leni 作为 long long int 解决了这个问题,这样添加了 long long int

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

另外我忘记检查 malloc returns NULLmain() 函数中。

这是正确的版本:

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