Calloced内存似乎为空

Calloced内存似乎为空,c,dynamic-allocation,calloc,finite-element-analysis,C,Dynamic Allocation,Calloc,Finite Element Analysis,有哪些可能的情况可以使以下代码执行以下代码段中的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

有哪些可能的情况可以使以下代码执行以下代码段中的
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);}
#包括
#包括
真空总管(真空){
int Nod=1024*8;//Nod包含节点数
double*MM;//MM是一个方阵,它可以包含大量数据10^10
MM=calloc(8*Nod*8*Nod,sizeof(双));
如果(MM==NULL)退出(0);
//然后MM将被传递给其他一些函数,比如
特征值(MM);}
我正在使用一个FEM代码,在一个非常大的程序中间有这个检查。有趣的是,当我运行代码时,它显示异常行为。有时程序就停在这里。有时它只是工作得很好。值得一提的是,当程序使用粗网格运行时,即当
Nod
要计算的节点数较少时,程序工作正常。但当使用精细网格时,程序不幸崩溃。该程序在具有128GB Ram的小型工作站上运行。该程序占用1GB左右的RAM。

两个明显的问题:


  • 计算
    8*Nod*8*Nod
    的类型为
    int
    ,该类型可能不够大(在您的平台上)无法容纳结果。您可能希望使用
    size\u t Nod
    。如果值不是常量,您可能需要检查溢出(可能是使用特定于平台的函数,如GCC的
    \uuuu内置的
  • 使用
    calloc()
    的结果时,不检查它是否为
    NULL
    。如果分配器找不到足够大的连续块,它将失败,您应该在继续之前对此进行测试
  • 永远不要忽略用于报告错误的库函数的返回值。

    两个明显的问题:


  • 计算
    8*Nod*8*Nod
    的类型为
    int
    ,该类型可能不够大(在您的平台上)无法容纳结果。您可能希望使用
    size\u t Nod
    。如果值不是常量,您可能需要检查溢出(可能是使用特定于平台的函数,如GCC的
    \uuuu内置的
  • 使用
    calloc()
    的结果时,不检查它是否为
    NULL
    。如果分配器找不到足够大的连续块,它将失败,您应该在继续之前对此进行测试
  • 永远不要忽略用于报告错误的库函数的返回值。

    从手册页:

       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字节)。 现在,您的系统肯定有那个数量的ram,但在任何给定的时间,它可能不会在一个连续的可分配块中拥有全部ram,因此calloc可能会因此而失败

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

    /proc/sys/vm/overcommit_memory
    or vis sysctl  vm.overcommit_memory
    
    默认情况下,Overmit_内存设置为0,但最安全的组合可能是将其设置为2。请参阅proc手册页或内核文档/vm/overmit accounting以了解更多有关此方面的详细信息

    vm.overcommit_ratio
    vm.overcommit_kbytes
    vm.nr_overcommit_hugepages
    
    还有其他sysctl设置,用于控制系统是否/如何处理内存过多问题

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

    从手册页:

       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字节)。 现在,您的系统肯定有那个数量的ram,但在任何给定的时间,它可能不会在一个连续的可分配块中拥有全部ram,因此calloc可能会因此而失败

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

    /proc/sys/vm/overcommit_memory
    or vis sysctl  vm.overcommit_memory
    
    默认情况下,Overmit_内存设置为0,但最安全的组合可能是将其设置为2。有关详细信息,请参阅proc手册页或内核文档/vm/Overmit accounting

    vm.overcommit_ratio
    vm.overcommit_kbytes
    vm.nr_overcommit_hugepages
    
    还有其他sysctl设置,用于控制系统是否/如何处理内存过多问题


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

    无论执行何种分支,特定程序总是以零状态返回。主功能(仅主功能)当执行到达结束括号并返回时,有一个隐式的
    返回0;
    8*Nod*8*Nod
    是2²,因此是整数溢出。请使用大于
    int
    的类型。请阅读calloc和可能返回值的手册页。如果使用稀疏矩阵,则只需存储在映射或无序映射。无需分配大量内存。较大的类型为谁?
    Nod
    Nod
    仅表示要计算的节点数,这在
    int
    数据类型的范围内。该特定程序始终以零状态返回,而不管执行何种分支。主函数(并且只有主函数)具有隐式
    返回0;