首页 > 解决方案 > 使用“calloc”进行内存分配失败

问题描述

我正在尝试使用calloc函数分配内存,但是当数组大小(类型double)为 48,000 x 48,000 时,它返回 NULL 指针。但是,它非常适用于 23,000 x 23,000 的另一种情况。从技术上讲,应该没有问题,因为我在这台计算机上有足够的 RAM。我也在使用 64 位库。

操作系统:Linux 64位

安装内存:376GB

编译器:英特尔 MKL 2019

编译器链接行:

icc Main.c -qopenmp -DMKL_ILP64 -m64 -I$MKLROOT/include \
    -L$MKLROOT/lib/intel64 -lmkl_intel_ilp64 -lmkl_intel_thread \
    -lmkl_core -liomp5 -lpthread -lm -ldl -O2 -o main.out

这里是我使用的一段代码:

int Jsize = 48000;
double *J = NULL;
J = (double *)calloc(Jsize*Jsize, sizeof(double));
if (J == NULL) printf("Null\n");

标签: c

解决方案


您有一个int名为 的对象Jsize,初始化为 48000。然后您计算Jsize*Jsize。该表达式的数学值为 ,2304000000超过 2 31 -1。

系统上的类型int几乎可以肯定是 32 位,这意味着乘法会溢出。行为未定义,但很可能您会得到否定的结果。

请记住,C 中表达式的类型是由表达式本身决定的,而不是由计算它的上下文决定的。将 an 乘以intanint总是会产生int结果,即使该结果被分配给更大的值。

然后将该值作为第一个参数传递给calloc(),它需要一个类型为 的参数size_t。如果size_t是 64 位(它可能是),那么你传递了一个巨大的正值,可能18446744071718584320如果我的计算是正确的。

在我的 64 位 Ubuntu 系统上,当我printf向您的代码添加几个调用时,我得到:

Jsize*Jsize = -1990967296
(size_t)(Jsize*Jsize) = 18446744071718584320
Null

你没有那么多记忆。

如果你Jsize用 type定义size_t,你至少可以尝试分配你想要的 17+ GiB。(在我的系统上,calloc失败ENOMEM,但我没有你那样多的 RAM。)

但是请注意,操作系统可能不允许您为一个进程分配那么多内存。


推荐阅读