Reputation: 157
What are the possible cases that can make the following code to execute the if
condition in the following snippet? As far as I'm concerned, I can't relate any cause for the if
statement to execute.
#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);}
I'm working with a FEM code that has this check in the middle of a very large program. The interesting fact is when I run the code, it shows anomalous behavior. Sometimes the program stops just here. Sometimes it just works fine. One thing that is worthy to be mentioned that is when the program is run with coarse mesh i.e. when Nod
has less number of nodes to calculate, the program just works fine. But when a fine mesh is used, the program crashes unfortunately. This program is run in a mini workstation which have 128GB Ram. The program occupies 1GB (or so) of RAM.
Upvotes: 1
Views: 182
Reputation: 743
From the man page:
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
Now in your case it's not dew to allocating zero sized memory so the only other reason for returning NULL is failure to allocate the memory. In the snippet you show you are allocating 4294967296 elements (1024 * 1024 * 64 * 64) the size of a double (8 bytes) that's 32Gb of ram. Now your system definitely has that amount of ram but at any given time it may not have it all in a consecutive allocable block so calloc may be failing for that reason.
Another thing to watch out for is memory overcommitment governed primarily by
/proc/sys/vm/overcommit_memory
or vis sysctl vm.overcommit_memory
by default overcommit_memory is set to 0 but possibly the safest combination would be setting it to 2. See proc man page or kernel Documentation/vm/overcommit-accounting for more detail on this.
vm.overcommit_ratio
vm.overcommit_kbytes
vm.nr_overcommit_hugepages
are also other sysctl settings that govern if/how your system will deal with memory overcommitment.
Even at this I've done my best not to allow overcommitment of memory on a 32 bit linux machine but I was still able to get the huge 32Gb callot not to return null (which I regard as being strange on it's own as a PAE less 32 bit machine can only address a total of 4Gb of virtual memory, and even if it had PAE it would only allow addressing 4Gb at a time).
Upvotes: 0
Reputation: 30873
Two obvious problems:
8 * Nod * 8 * Nod
will be of type int
, which might not be big enough (on your platform) to hold the result. You probably want size_t Nod
instead. And you might want to check for overflow (perhaps with platform-specific functions such as GCC's __builtin_mul_overflow()
) if the values are not constant.calloc()
without checking that it's not NULL
. If the allocator can't find a big enough contiguous block, it will fail, and you should test for that before continuing.Never ignore the return value from library functions that use it to report errors.
Upvotes: 6