调用的内存似乎为 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。
两个明显的问题:
- 计算
8 * Nod * 8 * Nod
将是 int
类型,它可能不够大(在您的平台上)来保存结果。您可能需要 size_t Nod
来代替。如果值不是常量,您可能想要检查溢出(可能使用特定于平台的函数,例如 GCC 的 __builtin_mul_overflow()
)。
- 您使用了
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。
有哪些可能的情况可以使以下代码执行以下代码段中的 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。
两个明显的问题:
- 计算
8 * Nod * 8 * Nod
将是int
类型,它可能不够大(在您的平台上)来保存结果。您可能需要size_t Nod
来代替。如果值不是常量,您可能想要检查溢出(可能使用特定于平台的函数,例如 GCC 的__builtin_mul_overflow()
)。 - 您使用了
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。