Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用一维数组的C-malloc分割错误_C_Segmentation Fault_Malloc - Fatal编程技术网

使用一维数组的C-malloc分割错误

使用一维数组的C-malloc分割错误,c,segmentation-fault,malloc,C,Segmentation Fault,Malloc,我使用malloc在C中创建一个数组。但是当我试图在2个循环中为数组分配随机值时,我遇到了分段错误 当我在1个循环中为这个数组赋值时,没有分段错误。数组大小很大。请看我附上的代码。 任何人都可以告诉我这里发生了什么。我是C的新手,提前多谢了 int n=50000; float *x = malloc(n*n*sizeof(float)); // there is segmentation fault: int i, j; for (i=0; i<n; i++){ for (j=0

我使用malloc在C中创建一个数组。但是当我试图在2个循环中为数组分配随机值时,我遇到了分段错误

当我在1个循环中为这个数组赋值时,没有分段错误。数组大小很大。请看我附上的代码。 任何人都可以告诉我这里发生了什么。我是C的新手,提前多谢了

int n=50000;
float *x = malloc(n*n*sizeof(float));

// there is segmentation fault:
int i, j;
for (i=0; i<n; i++){
   for (j=0; j<n; j++){
       x[i*n+j] = random() / (float)RAND_MAX;
    }
}
// there is no segmentation fault:
int ii;
for (ii=0; ii<n*n; ii++){
        x[ii] = random() / (float)RAND_MAX;
}
int n=50000;
float*x=malloc(n*n*sizeof(float));
//存在分段错误:
int i,j;

对于(i=0;i
int
溢出)

float *x = malloc(sizeof(float)*n*n);
50000*50000
-->2500000000-->超过
INT\u MAX
-->未定义行为(UB)

首先,让我们确定这一分配规模的计算是可能的

assert(SIZE__MAX/n/n/sizeof(float) >= 1);
然后,使用足够宽的验证
size\u t
,使用
size\u t
math进行乘法,并使用
size\u t
math进行数组索引计算。而不是
int*int*size\u t
,而是
size\u t*int*int

// float *x = malloc(n*n*sizeof(float));

// Uses at least `size_t` math by leading the multiplication with that type.
float *x = malloc(sizeof(float) * n*n);
// or better
float *x = malloc(sizeof *x * n*n); 

for (i=0; i<n; i++){
  for (j=0; j<n; j++){
    x[(size_t)n*i + j] = random() / (float)RAND_MAX;
  }
}
//float*x=malloc(n*n*sizeof(float));
//通过使用该类型的乘法,至少使用'size\t'数学。
float*x=malloc(sizeof(float)*n*n);
//或者更好
float*x=malloc(sizeof*x*n*n);

对于(i=0;i首先,由于有符号整数溢出而调用。假设
int
为32位,则50000*50000的值超出
int
的范围,从而导致溢出

float *x = malloc(sizeof(float)*n*n);
您可以通过将
sizeof(float)
放在表达式的第一位来解决此问题。
sizeof
的结果是一个
size\u t
,它是无符号的,至少与
int
一样大。然后当每个
n
相乘时,它首先转换为
size\u t
,从而避免溢出

float *x = malloc(sizeof(float)*n*n);
然而,即使你解决了这个问题,你也需要太多的内存

假设
sizeof(float)
是4个字节,
n*n*sizeof(float)
大约是10GB的内存。如果检查
malloc
的返回值,您可能会看到它返回NULL


您需要使数组小得多。请尝试使用
n=1000
,它将只使用大约4MB。

我认为问题与整数溢出有关:

50000*50000=25亿

2^31~21亿

因此,在计算数组索引时,您正在调用未定义的行为。至于为什么它适用于一个而不适用于另一个,这就是它的方式。未定义的行为意味着编译器(和计算机)可以做任何它想做的事,包括做您期望的事情和使程序崩溃

要修复,请将i、j、n和ii的类型从int改为long-long。这将解决溢出问题和分段错误

编辑:


在对指针执行操作之前,您还应该检查malloc是否返回有效指针。如果malloc失败,您将收到一个空指针。

谢谢!我学到了很多。当我使用size\t进行索引计算x[(size\t)n*I+j]时,问题得到了解决。我在开始时将n定义为size\t。