Common mistakes with memory allocation
Comments and questions to John Rowe.
This is the ultimate memrory allocation error and will lead to disaster.
|
Bad |
Good |
double *p;
int n = 8;
for(int i = 0; i < n; ++i )
p[i] = i*2;
|
double *p;
int n = 8;
p = xmalloc(n*sizeof *p);
for(int i = 0; i < n; ++i )
p[i] = i*2;
|
|
Bad |
Good |
double *p;
int n = 8;
p = malloc(n*sizeof *p);
for(int i = 0; i < n; ++i )
p[i] = i*2;
|
double *p;
int n = 8;
p = malloc(n*sizeof *p);
if ( p == NULL ) {
fprintf(stderr, "Out of memory!\n");
exit(1);
}
for(int i = 0; i < n; ++i )
p[i] = i*2;
|
|
Better |
|
void *xmalloc(size_t n) {
void *p = malloc(n);
if (p == NULL) {
fprintf(stderr, "Out of memory!\n");
exit(1);
}
return p;
}
void anotherfunction(void) {
double *p;
int n = 8;
p = xmalloc(n*sizeof *p);
for(int i = 0; i < n; ++i )
p[i] = i*2;
}
|
- Ordinary array declaration is fast and the memory is automatically
released when the function returns.
- Dynamic memory allocation is slow and is permenant until freed.
So:
- Use normal arrays when the array is not needed after the function returns.
- Use dynamic allocation when it is.
|
Poor |
Better |
#include <stdlib.h>
void poorfun(int n) {
double *x;
x = xmalloc(n * sizeof *x);
free(x);
}
|
void betterfun(int n) {
double x[n];
}
|
The first version has more ways to go wrong, we might forget to
call free(), and is also slower. (However, until C99
programmers had no choice as array sizes had to be declared at
compile time.) It's not unknown for the speed of some programs
to be dominated by calls to malloc().
|
This is the reverse of the previous one but is much more
serious as the program will give the wrong answers or crash.
|
Bad |
Better |
int **badnew2dint(int m, int n) {
int *p[m];
int i;
for (i = 0; i < m; ++i)
p[i] = malloc(n * sizeof *p[i]);
return p; }
|
int **new2dint(int m, int n) {
int **p;
int i;
p = xmalloc(m * sizeof *p);
for (i = 0; i < m; ++i)
p[i] = malloc(n * sizeof *p[i]);
return p;
}
|