对于大于4GiB的阵列,64位系统上的calloc调用失败

Bas*_*ler 1 c linux 64-bit segmentation-fault calloc

注意:我是学习C的新手,这可能是一个我完全不知道的完全简单的解决方案.在那种情况下,请赐教我.

我在调试C程序时遇到问题,我是从同事处收到的.从本质上讲,我设法将段错误跟踪到失败的调用,calloc()如果n大于46341:

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;
}
Run Code Online (Sandbox Code Playgroud)

ideone上的代码相同.

AFAIK,这恰好评估为4GiB,这就是我怀疑的原因.我试过的系统都是64位,所以分配不应该是个问题.在SO上搜索已经提出了calloc()可能无法找到连续空间的想法,所以我尝试了多次调用calloc(),并试图调用realloc().最后,我试图实现分配n C++,其中调用会float *v = new float[n * (n - 1)/2]()引发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

老实说,我没有想法.

Nom*_*mal 6

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

解决方案是使用

size_t ngenes = 46341;
Run Code Online (Sandbox Code Playgroud)

代替.size_t是应该用于内存中对象的大小和长度的类型.

  • 非常感谢,我发誓我已经尝试过这个,但是在您的建议之后,我尝试验证它并且它正在工作。我责怪第四杯红酒。 (2认同)