调用的内存似乎为 NULL

Calloced memory appears to be NULL

有哪些可能的情况可以使以下代码执行以下代码段中的 if 条件?就我而言,我无法将 if 语句执行的任何原因联系起来。

#include <stdio.h>
#include <stdlib.h>
void main(void){
int Nod = 1024 * 8; //Nod contains the number of nodes
double *MM; //MM is a square matrix it can contain very large number of data 10^10
MM = calloc(8 * Nod * 8 * Nod, sizeof(double));
if (MM == NULL)exit(0);
//then MM will then be passed to some other functions say
eigenvalue(MM);}

我正在使用一个 FEM 代码,该代码在一个非常大的程序中间进行了此检查。有趣的是,当我 运行 代码时,它显示出异常行为。有时程序就在这里停止。有时效果很好。值得一提的是,当程序 运行 具有粗网格时,即当 Nod 要计算的节点数较少时,程序运行良好。但是当使用细网格时,不幸的是程序崩溃了。该程序是 运行 在具有 128GB Ram 的迷你工作站中。该程序占用 1GB(左右)的 RAM。

两个明显的问题:

  1. 计算 8 * Nod * 8 * Nod 将是 int 类型,它可能不够大(在您的平台上)来保存结果。您可能需要 size_t Nod 来代替。如果值不是常量,您可能想要检查溢出(可能使用特定于平台的函数,例如 GCC 的 __builtin_mul_overflow())。
  2. 您使用了 calloc() 的结果,但没有检查它不是 NULL。如果分配器找不到足够大的连续块,它将失败,您应该在继续之前进行测试。

永不 忽略使用它报告错误的库函数的 return 值。

来自手册页:

   The malloc() and calloc() functions return a pointer to the allocated  memory  that
   is  suitably  aligned  for  any kind of variable.  On error, these functions return
   NULL.  NULL may also be returned by a successful call to malloc() with  a  size  of
   zero, or by a successful call to calloc() with nmemb or size equal to zero.e here

现在,在您的情况下,分配零大小的内存并不是露水,因此 returning NULL 的唯一其他原因是无法分配内存。 在您显示的片段中,您正在分配 4294967296 个元素(1024 * 1024 * 64 * 64),即 32Gb 内存的双精度(8 字节)大小。 现在你的系统肯定有那个数量的 ram 但在任何给定时间它可能不会在连续的可分配块中全部拥有所以 calloc 可能因此而失败。

另一件需要注意的事情是内存过度使用主要由

控制
/proc/sys/vm/overcommit_memory
or vis sysctl  vm.overcommit_memory

默认情况下 overcommit_memory 设置为 0,但最安全的组合可能是将其设置为 2。请参阅 proc 手册页或内核 Documentation/vm/overcommit-accounting 了解更多详细信息。

vm.overcommit_ratio
vm.overcommit_kbytes
vm.nr_overcommit_hugepages

还有其他管理 if/how 的 sysctl 设置,您的系统将处理内存过量使用。

即便如此,我也已尽最大努力不允许在 32 位 linux 机器上过度使用内存,但我仍然能够获得巨大的 32Gb 调用,而不是 return null (我认为它本身很奇怪,因为没有 PAE 的 32 位机器只能寻址总共 4Gb 的虚拟内存,即使它有 PAE,它也只能一次寻址 4Gb。