I'm working with matrices in C and looking to improve my code and ensure there are no memory leaks.
My matrix implementation looks like:
typedef struct {
int nb_cols;
int nb_rows;
float *data;
} matrix;
I have a lot of functions that take two matrices as input, and return an output. They look like this:
matrix *function(matrix* m1, matrix *m2)
{
matrix* temp = matrix_init(m1->rows, m1->cols);
// Doing some stuff
// like temp[i * (m1->cols) j] = m1[ i * (m1->cols j] m2[i * (m2->cols j];
// (this is just an example)
return temp;
}
When I call those functions like this:
mat = function1(function2(m1, m2), m3);
Does the compiler automatically allows temporary matrices and then frees ? Or should I never do this and have all the temporary matrices to do the operations one by one and free ?
Is writing this any better?:
mat_temp = function2(m1, m2);
mat = function1(mat_temp, m3);
free(mat_temp);
Thanks a lot for your answers!
CodePudding user response:
2nd is better.
With below, the pointer returned by function2()
is lost and so the memory allocated to it lacks a corresponding free()
. Memory leak
// lost memory
mat = function1(function2(m1, m2), m3);
Instead:
matrix *m1 = function0();
matrix *m2 = function0();
matrix *mat_temp = function2(m1, m2);
matrix *mat = function1(mat_temp, m3);
free(mat_temp);
...
free(mat);
free(m2);
free(m1);
Asides:
improve my code
If the data pointed to does not change, add const
to allow for wider function usages and some optimizations.
// matrix *function(matrix* m1, matrix *m2)
matrix *function(const matrix* m1, const matrix *m2)
If the calling code should never provide overlapping data (no surprising data changes), add restrict
to let the compiler apply more optimizations.
// matrix *function(matrix* m1, matrix *m2)
matrix *function(matrix* restrict m1, matrix * restrict m2)
... or both const
and restrict
.
Good code also tests for failed allocations.
if (m == NULL) TBD_code();
CodePudding user response:
Does the compiler automatically allows temporary matrices and then frees?
No, the compiler doesn't automatically frees them.
You can allocate some matrix data on the stack (using the VLA - variable-length array feature in C99), but if you want to pass it to some other subroutine, you have to use heap (malloc, calloc, realloc, and free, and a few other platform-specific ones)
Or should I never do this, and use temporary matrices to process operations one after another and then free temporary matrices
If you're unfamiliar with memory management, and is willing to sacrifice efficiency for correctness, allocate-copy-free isn't a bad stratagy.
But take my words with a grain of salt, as I've not been programming with memory management for quite some time.
What I've been doing with my recent personal project is that, I allocate all variables statically, by estimating the maximum necessary memory first, then allocate, and never free any of the working context throughout the life time of the program.