1

哪些可能的情况可以使以下代码执行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 内存的迷你工作站中运行。该程序占用 1GB(左右)的 RAM。

4

2 回答 2

6

两个明显的问题:

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

永远不要忽略使用它来报告错误的库函数的返回值。

于 2017-03-13T09:55:43.803 回答
0

从手册页:

   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

现在,在您的情况下,分配零大小的内存不是露水,因此返回 NULL 的唯一其他原因是未能分配内存。在您展示的片段中,您正在分配 4294967296 个元素(1024 * 1024 * 64 * 64),其大小为 32Gb ram 的双精度(8 字节)。现在您的系统肯定有这么多内存,但在任何给定时间,它可能不会将所有内存都放在一个连续的可分配块中,因此 calloc 可能因此而失败。

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

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

默认情况下,overcommit_memory 设置为 0,但最安全的组合可能是将其设置为 2。有关此内容的更多详细信息,请参见 proc 手册页或内核文​​档/vm/overcommit-accounting。

vm.overcommit_ratio
vm.overcommit_kbytes
vm.nr_overcommit_hugepages

还有其他 sysctl 设置,用于控制您的系统是否/如何处理内存过度使用。

即使在这一点上,我已经尽我所能不允许在 32 位 linux 机器上过度使用内存,但我仍然能够让巨大的 32Gb callot 不返回 null (我认为它本身很奇怪,因为它少了 PAE 32 位机器总共只能寻址 4Gb 的虚拟内存,即使它有 PAE,它一次也只允许寻址 4Gb)。

于 2017-03-13T10:11:12.407 回答