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

标签 c linux segmentation-fault 64-bit calloc

注意:我是学习 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() 可能无法找到连续空间的想法,因此我尝试了几次对 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); 返回 18446744073709551615

老实说,我没有想法。

最佳答案

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

解决方案是使用

size_t ngenes = 46341;

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

关于对于大于 4GiB 的数组,在 64 位系统上调用 calloc 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31999530/

相关文章:

c++ - 调试段错误

c - char *str ="STRING"和 char str[] = "STRING"之间的区别?

c - UNIX C 中的 gcc -lcrypt 标志错误 - 未定义对 crypt() 的引用

c - 读写器访问多个读者

c - Write() 给出奇怪的整数符号

c - 填充结构 C 时出现段错误,缩小为一行

python - 从另一个位置运行时如何在 linux 上获取绝对路径

Python执行远程ssh命令

linux - Shell感叹号命令

c++ - 在程序中使用同一类的两个不同堆栈时出现段错误