malloc is failing to allocate memory

541 Views Asked by At

I'm writing a C Code to solve Euler equations. My code works perfectly fine on the cluster but not on my pc. Seems to be an issue with malloc(). It is not being able to allocate the requested memory and fails.

How do i make it work? is it something to do with Defragmentation? But the system settings show (0% Defragmented).

Just including a part of malloc() code here.

double **u, **rho_u, **rho,    
int Size = 1000;
u = (double**)malloc(Size*sizeof(double*));
for(i=0;i<=Size;i++)
    u[i] = (double*)malloc(Size*sizeof(double));

rho_u = (double**)malloc(Size*sizeof(double*));
for(i=0;i<=Size;i++)
    rho_u[i] = (double*)malloc(Size*sizeof(double));
3

There are 3 best solutions below

2
On BEST ANSWER

You probably corrupt your heap here:

for(i=0;i<=Size;i++)
    u[i] = (double*)malloc(Size*sizeof(double));

You assign 1001 pointers, but only have 1000 allocated. Correct version:

for(i=0;i<Size;i++)
    u[i] = (double*)malloc(Size*sizeof(double));

Same for the second loop.

2
On

Read carefully the documentation of malloc. It can fail, and when it does fail, malloc returns NULL (and the failure reason is given by errno which you often display using perror).

So you should test against failure of malloc. The typical code is at least:

u = (double**)malloc(Size*sizeof(double*));
if (u==NULL) { perror ("malloc u"); exit(EXIT_FAILURE); };

and likewise for your rho_u and every rho_u[i]

Some operating systems may provide memory overcomitment. It is a feature I dislike.

Consider initializing every memory zone entirely. And using memory outside of a valid memory zone (or a valid address) is undefined behavior (and your program have one, noticed by Ctx's answer). Be scared.

I also recommend using valgrind. It is a very handy tool to hunt memory related bugs, and could have detected yours.

1
On

Observation :

  • Avoid typecasting malloc(), Read Do I cast the result of malloc?
  • Check the return value of malloc() & do proper error handling.
  • Change loop condition from i<=Size to i<Size as it cause buffer overrun since earlier memory was allocated only for Size rows not size+1 rows.

Try this version :

int Size = 1000;
double **u = malloc(Size * sizeof(*u)); /* typecasting is not needed */
if(u == NULL) {
   /* @TODO error handling */
}
for(i=0;i<Size;i++) { /* loop should rotate only 1000 times not 1001 times */
    u[i] = malloc(Size * sizeof(**u));
    if(u[i] == NULL) {
         /* @TODO error handling */
    }
}

Similarly for rho_u and rho.