对于大于 4GiB 的数组,在 64 位系统上调用 calloc 失败

Call to calloc fails on 64 Bit system for arrays which are greater than 4GiB

注意:我刚开始学习 C,这可能有一个我不知道的完全简单的解决方案。既然如此,还请赐教。

我在调试 C 程序时遇到问题,这是我从同事那里收到的。本质上,如果 n 大于 46341:

,我设法将段错误跟踪到对 calloc() 的失败调用

float *v = (float*) calloc(n * (n - 1)/2, sizeof(float));

下面是一组触发问题的最少代码:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]){

    int ngenes = 46341;

    float *v = (float*) calloc(ngenes * (ngenes - 1)/2, sizeof(float));
    if(v) printf("Allocation succeeded\n");
    free(v);

    ngenes++;

    v = (float*) calloc(ngenes * (ngenes - 1)/2, sizeof(float));
    if(v) printf("Allocation succeeded\n");
    free(v);

    return 0;
}

ideone 上的相同代码。

据我所知,这正好是 4GiB,这就是我怀疑的原因。我试过的系统都是64位的,所以分配应该不是问题。在 SO 上四处搜索提出 calloc() 可能无法找到连续的 space,因此我尝试了几次对 calloc() 的调用,还尝试调用 realloc() .最后,我尝试通过调用 float *v = new float[n * (n - 1)/2]() 来实现分配 n C++,这会引发 bad_alloc 错误。

我一直在尝试的系统:

$ uname -a
Linux picea 3.13.0-35-generic #62-Ubuntu SMP Fri Aug 15 01:58:42 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ free
             total       used       free     shared    buffers     cached
Mem:     396222336  368621612   27600724      32320     281536  346677332
-/+ buffers/cache:   21662744  374559592
Swap:    125061116   64894524   60166592

我试过编译:

gcc -m64 ...

无济于事。 运行 printf("%lu\n",SIZE_MAX); returns 18446744073709551615

老实说,我没有想法。

您很可能是在 LP64 架构上编译它,其中 int 是 32 位,但 long 和指针是 64 位。大小计算最终以整数精度完成,然后 提升为 64 位,因此产生不正确的大小(负数,或比预期短得多)。

解决方案是使用

size_t ngenes = 46341;

相反。 size_t 是您应该用于内存中对象的大小和长度的类型。