使用一维数组的C-malloc分割错误
我使用malloc在C中创建一个数组。但是当我试图在2个循环中为数组分配随机值时,我遇到了分段错误 当我在1个循环中为这个数组赋值时,没有分段错误。数组大小很大。请看我附上的代码。 任何人都可以告诉我这里发生了什么。我是C的新手,提前多谢了使用一维数组的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
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;iint
溢出)
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。