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

时间:2019-03-29 02:46:51

标签: 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; 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;
}

3 个答案:

答案 0 :(得分:5)

InterruptedException溢出。

int-> 2,500,000,000->超过50000 * 50000->未定义行为(UB)。

首先,让我们确定此分配的大小是可能的

INT_MAX

然后使用经过验证的assert(SIZE__MAX/n/n/sizeof(float) >= 1); 宽度,使用size_t数学进行乘法,然后使用size_t数学进行数组索引计算。而不是size_t,而是进行int*int*size_t

size_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; } } 并不是期望的大值,而是分配中的UB值相同。

答案 1 :(得分:3)

首先,由于有符号整数溢出,您正在调用undefined behavior。假设int是32位,则50000 * 50000的值超出了int的范围,导致溢出。

您可以通过在表达式的前面放置sizeof(float)来解决此问题。 sizeof的结果是一个size_t,它是无符号的,并且至少与int一样大。然后,当每个n相乘时,首先将其转换为size_t,从而避免溢出。

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

但是,即使您解决此问题,您仍需要太多内存。

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

您需要使数组更小。尝试使用n=1000,它将仅使用大约4MB。

答案 2 :(得分:1)

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

50,000 * 50,000 = 25亿

2 ^ 31〜21亿

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

要修复,请将i,j,n和ii的类型从int更改为long long。那应该可以解决溢出问题和分段错误。

编辑:

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