【问题标题】:Segmentation fault in malloc()malloc() 中的分段错误
【发布时间】:2021-11-17 02:04:15
【问题描述】:

我需要创建一个返回整数数组的函数。这个 int 数组应该包含 min 和 max 之间的所有值(都包括在内)。

  • 如果 min >= max,则应返回空指针。

问题是为什么当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 = 2147483646len = 4294967295 就可以了。

【问题讨论】:

  • len = max - min + 1; --> len = 1L + max - min; 避免intlong 更宽时溢出。最好使用size_t len(size_t)1
  • 假设long int大于int,所以它不是可移植代码,但它可以在OP的系统上运行。
  • 您确定您向我们展示的代码中出现了段错误吗?请提供minimal reproducible example(包括函数main)。
  • 你的编译器和操作系统是什么?另外,使每个变量long long int
  • min = -2147483647 - 1;替换min = -2147483648;以避免UB。

标签: c malloc


【解决方案1】:

minmaxint 类型,仅保证为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 的内存,所以我希望你已经准备好了。

【讨论】:

  • 不起作用。添加了一个 main() 函数,因为我怀疑它也可能存在错误
  • 如果您的系统无法分配 16 GB 内存或 size_T 小于 long long int,它将不起作用(malloc 将返回 NULL)。您是否确认 malloc 没有返回 NULL
  • 谢谢您,采纳了您的一些建议并解决了问题。
【解决方案2】:

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

【讨论】:

  • 我唯一允许的函数是 malloc,对不起。添加了一个 main() 函数,因为我怀疑它也可能存在错误
  • @RaphaelRakhimov 你在这个答案中看到了什么其他功能?
【解决方案3】:

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

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

另外我忘了检查malloc 是否在main() 函数中返回NULL

这是正确的版本:

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

【讨论】:

  • sizeof(int) * len &gt; SIZE_MAX 时,此代码与malloc(sizeof(int) * len) 存在问题,导致未定义行为 (UB)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
  • 2015-01-29
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
相关资源
最近更新 更多