Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid memory leak when passing function-returned pointer as input to other function?

I'm trying to write a simple C matrix library that dynamically allocates the memory required and that allows to "nest" function calls (like fun1(fun2(x))) in order to avoid declaring too many temporary variables when performing long operations. However I cannot get rid of the memory leak caused by never freeing the structs created inside the functions. The example below clearly shows that. Any suggestion on how to solve that without declaring other temporary variables?

Thanks a lot

#include <stdio.h>
#include <stdlib.h>

struct _MatrixF{
    uint8_t rows;
    uint8_t cols;
    float* mat;
};
typedef struct _MatrixF* Matrix;

Matrix newMatrix(uint8_t rows, uint8_t cols){
    Matrix matrix = malloc(sizeof(struct _MatrixF));
    matrix->rows = rows;
    matrix->cols = cols;
    matrix->mat = malloc(rows * cols * sizeof(float));
    return matrix;
}

Matrix matIdentity(uint8_t rows, uint8_t cols){
    Matrix matrix = newMatrix(rows, cols);
    uint16_t ii;
    for (ii = 0; ii < (cols * rows); ii++)
        matrix->mat[ii] = (((ii / cols) == (ii % cols))? 1.0f : 0.0f);
    return matrix;
}


Matrix matAdd(Matrix lhs, Matrix rhs){
    Matrix m = newMatrix(lhs->rows, lhs->cols);
    uint16_t ii;
    for (ii = 0; ii < (lhs->cols * lhs->rows); ii++) {
        m->mat[ii] = lhs->mat[ii] + rhs->mat[ii];
    }
    return m;
}

Matrix matMult(Matrix lhs, Matrix rhs){
    uint8_t i, j, k;
    Matrix result = newMatrix(lhs->rows, rhs->cols);
    for (i=0; i < lhs->rows; i++)
        for (j=0; j < rhs->cols; j++)
            for (k=0; k < lhs->cols; k++)
                MAT(result, i, j) += MAT(lhs, i, k) * MAT(rhs, k, j);
    return result;
}

void mprint(Matrix m){
    printf("%dx%d\n", m->rows, m->cols);
    for(int i=0; i<m->rows; i++) {
        for (int j = 0; j<m->cols; j++)
            printf("%4.6f\t",(float) m->mat[(i) * m->cols + (j)]);
        printf("\n");
    }
}

int main(int argc, const char * argv[]) {
    Matrix A = matIdentity(4, 3);
    Matrix B = matIdentity(3, 2);
    Matrix C = matIdentity(2, 4);
    Matrix D = matIdentity(4, 4);
    uint16_t len = 64000;
    while (len--){
        Matrix E = matAdd(D, matAdd(D, matMult(matMult(A, B),C)));
        mprint(matMult(A, B));
        mprint(A);
        mprint(E);
    }
    return 0;
}
like image 517
Telli Avatar asked Jun 04 '26 06:06

Telli


1 Answers

C does not provide much help in dealing with this automatically. You can store pointers to temporary objects, and free them at the end of each iteration:

while (len--){
    Matrix t1, t2, t3, t4;
    Matrix E = matAdd(D, t1=matAdd(D, t2=matMult(t3=matMult(A, B),C)));
    mprint(t4=matMult(A, B));
    mprint(A);
    mprint(E);
    matFree(t1);
    matFree(t2);
    matFree(t3);
    matFree(t4);
}
like image 186
Sergey Kalinichenko Avatar answered Jun 05 '26 21:06

Sergey Kalinichenko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!