malloc() 中的分段错误
Segmentation fault in malloc()
我需要创建一个 returns 整数数组的函数。此 int 数组应包含最小值和最大值之间的所有值(均包含在内)。
- 如果 min >= max 应该返回空指针。
问题是,为什么当 min = -2147483468
和 max = 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 = -2147483468
和 max = 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;
}
min
和 max
是类型 int
,它只保证是 16 位有符号的(-32768、32767),尽管编译器可能会选择使用更多位来存储值。因此,如果您希望值的范围为 (-2147483468, 2147483647),则这些值的类型应为 long int
。当您提供 (-2147483468, 2147483647) 或 (-2147483468, 2147483646) 作为输入时,程序可能会或可能不会截断某些位。这也适用于 range
.
的类型
其次,变量len
是long int
,它只保证是32位有符号的(-2147483468、2147483647)。由于您希望能够存储值 4294967296,因此这需要是 long long int
或 long 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 的内存,因此我希望您已为此做好准备。
我通过使用 len
和 i
作为 long long int
解决了这个问题,这样添加了 long long int
:
len = (long long int)max - min + 1;
另外我忘记检查 malloc
returns NULL
在 main()
函数中。
这是正确的版本:
#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);
}
我需要创建一个 returns 整数数组的函数。此 int 数组应包含最小值和最大值之间的所有值(均包含在内)。
- 如果 min >= max 应该返回空指针。
问题是,为什么当 min = -2147483468
和 max = 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 = -2147483468
和 max = 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;
}
min
和 max
是类型 int
,它只保证是 16 位有符号的(-32768、32767),尽管编译器可能会选择使用更多位来存储值。因此,如果您希望值的范围为 (-2147483468, 2147483647),则这些值的类型应为 long int
。当您提供 (-2147483468, 2147483647) 或 (-2147483468, 2147483646) 作为输入时,程序可能会或可能不会截断某些位。这也适用于 range
.
其次,变量len
是long int
,它只保证是32位有符号的(-2147483468、2147483647)。由于您希望能够存储值 4294967296,因此这需要是 long long int
或 long 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 的内存,因此我希望您已为此做好准备。
我通过使用 len
和 i
作为 long long int
解决了这个问题,这样添加了 long long int
:
len = (long long int)max - min + 1;
另外我忘记检查 malloc
returns NULL
在 main()
函数中。
这是正确的版本:
#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);
}