Сумма матриц в возвращаемой матричной функции

#c #matrix #memory-leaks #dynamic-memory-allocation #function-definition

#c #матрица #утечки памяти #динамическое выделение памяти #функция-определение

Вопрос:

Ниже приведена компилируемая программа, большая часть которой сделана Крейгом Эсти, который помог мне с другим вопросом. Я просто использую его, чтобы люди могли протестировать программу, но проблема, с которой я сталкиваюсь, связана с функцией суммирования двух матриц. Точно, функция

 Matrix* sum(Matrix* mat1, Matrix* mat2){
    int row, col, k, l;
    Matrix *mat3;
    mat3 = allocateMemory(mat1->row, mat1->col);

    if((mat1->row == mat2->row)amp;amp;(mat1->col == mat2->col)){ //verify if the two matrices have the same order
        for (row = 0; row < mat1->row; row  ){
            for (col = 0; col < mat1->col; col  ){
                k = row * mat1->col   col;//create index for matrix 1 element
                l = row * mat2->col   col;//create index for matrix 2 element
                mat3->a[k] = mat1->a[k]   mat2->a[l]; //sum elements and store in mat3
            }
        }
        return mat3;
    }
}
 

Компилируемая программа на C

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

typedef struct matrix {
    int row;
    int col;
    int *a;
} Matrix;

Matrix *allocateMemory(int row, int col)
{
    Matrix *mat = malloc(sizeof(*mat));

    if (mat == NULL) {
        perror("malloc");
        exit(1);
    }

    mat->row = row;
    mat->col = col;

    mat->a = calloc(row * col, sizeof(*mat->a));
    if (mat->a == NULL) {
        perror("calloc");
        exit(1);
    }

    return mat;
}

void printMatrix(Matrix *mat)
{
    int row, col, off;

    for (row = 0; row < mat->row; row  ) {
        for (col = 0; col < mat->col; col  ) {
            off = (row * mat->col)   col;
            printf("%d   ", mat->a[off]);
        }
        printf("n");
    }
}

void matrix_fill(Matrix *mat)
{
    int row, col, off;
    int val = 1;

    for (row = 0; row < mat->row; row  ) {
        for (col = 0; col < mat->col; col  ) {
            off = (row * mat->col)   col;
            mat->a[off] = val  ;
        }
    }
}

Matrix* sum(Matrix* mat1, Matrix* mat2){
    int row, col, k, l;
    Matrix *mat3;
    mat3 = allocateMemory(mat1->row, mat1->col);

    if((mat1->row == mat2->row)amp;amp;(mat1->col == mat2->col)){
        for (row = 0; row < mat1->row; row  ){
            for (col = 0; col < mat1->col; col  ){
                k = row * mat1->col   col;
                l = row * mat2->col   col;
                mat3->a[k] = mat1->a[k]   mat2->a[l];
            }
        }
        return mat3;
    }
}

int main(void){

   Matrix *m1 = allocateMemory(3,3);
   Matrix *m2 = allocateMemory(3,3);
   Matrix *m3 = allocateMemory(3,3);

    matrix_fill(m1);
    matrix_fill(m2);

    printf("nMatrix 1n");
    printMatrix(m1);

    printf("nMatrix 2n");
    printMatrix(m2);

    Matrix* sum(Matrix* m1, Matrix* m2);
    printf("nSum of matrices m1 and m2n");
    printMatrix(m3);

    return 0;
}
 

Предполагается, что функция sum возвращает результат суммы двух заданных матриц, но она не работает, просто, кажется, возвращает нулевое значение. Но я не мог понять, почему это не работает.

Комментарии:

1. В сторону: чтобы избежать int переполнения огромными массивами. рассмотрим calloc(row * col, sizeof(*mat->a)); —> calloc((size_t)row * col, sizeof(*mat->a)); или тому подобное.

Ответ №1:

Функция имеет неопределенное поведение и утечку памяти, поскольку она ничего не может вернуть в случае, когда условие в операторе if

 if((mat1->row == mat2->row)amp;amp;(mat1->col == mat2->col)){
 

будет оценено как false.

Функция может быть объявлена и определена следующим образом

 Matrix * sum( const Matrix *mat1, const Matrix *mat2 )
{
    Matrix *mat3 = NULL;

    if ( ( mat1->row == mat2->row ) amp;amp; ( mat1->col == mat2->col ) )
    {
        mat3 = allocateMemory( mat1->row, mat1->col );
      
        if ( mat3 != NULL )
        {
            for ( int row = 0; row < mat1->row; row   )
            {
                for ( int col = 0; col < mat1->col; col   )
                {
                    int k = row * mat1->col   col;
                    mat3->a[k] = mat1->a[k]   mat2->a[k];
                }
            }
        }
    }

    return mat3;
}
 

В рамках функции main это распределение

 Matrix *m3 = allocateMemory(3,3);
 

является избыточным, а также приводит к утечке памяти, если вы вызовете функцию like (то есть, если вы вызовете функцию так, как это требуется).

 m3 = sum( m1, m2 );
 

И эта запись в основном

 Matrix* sum(Matrix* m1, Matrix* m2);
 

это объявление функции. Это не вызов функции.

Вы должны написать, как показано выше

 Matrix *m3 = NULL;

//...

m3 = sum( m1, m2 );