代码之家  ›  专栏  ›  技术社区  ›  EagleStar

显示错误的值:C指针还是malloc问题?

  •  1
  • EagleStar  · 技术社区  · 1 年前

    我的程序将矩阵1乘以矩阵2。矩阵3就是结果。 我可以用正确的值显示矩阵1和矩阵2,但我不能通过相同的函数显示矩阵3的期望值,尽管计算的值是好的。

    这里是我可以编译的代码。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct Dimensions {
        int dim1, dim2;
    };
    
    struct Dimensions enterDimensions(void);
    
    int **createMatrix(int, int);
    
    void deleteMatrix(int **);
    
    void displayMatrix(int **, int, int);
    
    int **multiply(int **, int **, int, int, int);
    
    int main(void) {
        struct Dimensions dimensions1 = enterDimensions();
        int **matrix1 = createMatrix(dimensions1.dim1, dimensions1.dim2);
        displayMatrix(matrix1, dimensions1.dim1, dimensions1.dim2);
        struct Dimensions dimensions2 = enterDimensions();
        int **matrix2 = createMatrix(dimensions2.dim1, dimensions2.dim2);;
        displayMatrix(matrix2, dimensions2.dim1, dimensions2.dim2);
    
        if (dimensions1.dim2 != dimensions2.dim1) {
            printf("the product of these matrixes does not exist");
        } else {
            int **matrix3 = multiply(matrix1, matrix2, dimensions1.dim1, dimensions1.dim2, dimensions2.dim2);
            displayMatrix(matrix3, dimensions1.dim1, dimensions2.dim2);
            deleteMatrix(matrix3);
        }
    
        deleteMatrix(matrix1);
        deleteMatrix(matrix2);
    
        return 0;
    }
    
    struct Dimensions enterDimensions(void) {
        int dim1;
        int dim2;
        struct Dimensions dimensions;
        printf("dim 1 : \n");
        scanf("%d", &dim1);
        printf("dim 2 : \n");
        scanf("%d", &dim2);
        dimensions.dim1 = dim1;
        dimensions.dim2 = dim2;
    
        return dimensions;
    }
    
    int **createMatrix(int dim1, int dim2) {
        printf("%s", "\ncreate matrix\n");
        int **matrix = malloc(dim1 * sizeof(int *));
        for (int i = 0; i < dim1; i++) {
            matrix[i] = malloc(dim2 * sizeof(int));
        }
    
        for (int i = 0; i < dim1; i++) {
            for (int j = 0; j < dim2; j++) {
                printf("enter (%d,%d)\n", i, j);
                scanf("%d", &matrix[i][j]);
                printf("%d\n", matrix[i][j]);
            }
        }
    
        return matrix;
    }
    
    void deleteMatrix(int **matrix) {
        printf("%s", "\ndelete matrix\n");
        free(matrix); // /!\ Warning : Parameter 'matrix' may point to deallocated memory when called from function 'main'
    }    
    
    void displayMatrix(int **matrix, int dim1, int dim2) {
        if (matrix == NULL) {
            exit(1);
        }
        for (int i = 0; i < dim1; i++) {
            for (int j = 0; j < dim2; j++) {
                if (j == dim2 - 1) {
                    printf("[%d]\n", matrix[i][j]);
                } else {
                    printf("[%d]", matrix[i][j]);
                }
            }
        }
    }
    
    int **multiply(int **matrix1, int **matrix2, int dim11, int dim12, int dim22) {
        int **matrix3 = malloc(dim11 * sizeof(int));
        for (int i = 0; i < dim11; i++) {
            for (int j = 0; j < dim22; j++) {
                int cij = 0;
                for (int k = 0; k < dim12; k++) {
                    if (matrix1 == NULL || matrix2 == NULL) {
                        exit(3);
                    }
                    cij += matrix1[i][k] * matrix2[k][j];
                }
    
                for (int l = 0; l < dim11; l++) {
                    matrix3[l] = malloc(dim22 * sizeof(int));
                }
                matrix3[i][j] = cij;
                printf("cij : %d\n", matrix3[i][j]);
            }
        }
        return matrix3;
    };
    

    这里是一个输出:

    dim 1 :
    2
    dim 2 :
    2
    
    create matrix
    enter (0,0)
    1
    1
    enter (0,1)
    0
    0
    enter (1,0)
    0
    0
    enter (1,1)
    1
    1
    [1][0]
    [0][1]
    dim 1 :
    2
    dim 2 :
    2
    
    create matrix
    enter (0,0)
    3
    3
    enter (0,1)
    3
    3
    enter (1,0)
    3
    3
    enter (1,1)
    3
    3
    [3][3]
    [3][3]
    cij : 3
    cij : 3
    cij : 3
    cij : 3
    [-253143104][428]
    [-253143104][3]
    
    delete matrix
    
    delete matrix
    
    delete matrix
    
    Process finished with exit code 0
    

    [-253143104][428]
    [-253143104][3]
    

    这是错误的结果。 在你看来,问题出在哪里? 谢谢。

    附言:如果你有一些改进我的代码的想法,不要犹豫,告诉我,因为我是一个初学者。

    PS2:如下所述,我在第一个malloc的乘法运算中忘记了int的*。但我仍然有问题。。。修正后。

    1 回复  |  直到 1 年前
        1
  •  1
  •   chqrlie    1 年前

    存在多个问题:

    • deleteMatrix 仅释放行指针数组。您应该传递行数( dim1 )因此它释放了保存矩阵值的各个行。

    • displayMatrix 应该简化:应该在内部循环的末尾无条件地输出换行符。

    • enterDimensions createMatrix 应检测并报告输入错误和分配失败。

    • multiplyMatrix 没有正确分配结果矩阵:它的行被多次分配给每个结果单元格值。最终结果是大量内存泄漏,并且只有每行的最后一个值在最终结果矩阵中显示正确。

    以下是修改后的版本:

    #include <stdio.h>
    #include <stdlib.h>
    
    struct Dimensions {
        int dim1, dim2;
    };
    
    struct Dimensions enterDimensions(void);
    int **allocateMatrix(int rows, int cols);
    int **createMatrix(int rows, int cols);
    void deleteMatrix(int **mat, int rows);
    void displayMatrix(int **mat, int rows, int cols);
    int **multiply(int **mat1, int **mat2, int dim11, int dim12, int dim22);
    
    int main(void) {
        struct Dimensions dimensions1 = enterDimensions();
        int **matrix1 = createMatrix(dimensions1.dim1, dimensions1.dim2);
        printf("matrix1:\n");
        displayMatrix(matrix1, dimensions1.dim1, dimensions1.dim2);
    
        struct Dimensions dimensions2 = enterDimensions();
        int **matrix2 = createMatrix(dimensions2.dim1, dimensions2.dim2);;
        printf("matrix2:\n");
        displayMatrix(matrix2, dimensions2.dim1, dimensions2.dim2);
    
        if (dimensions1.dim2 != dimensions2.dim1) {
            printf("cannot compute the product of these matrices: dimensions do not match\n");
            deleteMatrix(matrix1, dimensions1.dim1);
            deleteMatrix(matrix2, dimensions2.dim1);
            return 1;
        } else {
            int **matrix3 = multiply(matrix1, matrix2, dimensions1.dim1, dimensions1.dim2, dimensions2.dim2);
            printf("matrix3:\n");
            displayMatrix(matrix3, dimensions1.dim1, dimensions2.dim2);
            deleteMatrix(matrix3, dimensions2.dim2);
            deleteMatrix(matrix1, dimensions1.dim1);
            deleteMatrix(matrix2, dimensions2.dim1);
            return 0;
        }
    }
    
    struct Dimensions enterDimensions(void) {
        struct Dimensions dimensions;
        printf("enter dim 1: ");
        if (scanf("%d", &dimensions.dim1) != 1) {
            printf("invalid input\n");
            exit(1);
        }
        printf("enter dim 2: ");
        if (scanf("%d", &dimensions.dim2) != 1) {
            printf("invalid input\n");
            exit(1);
        }
        return dimensions;
    }
    
    int **allocateMatrix(int dim1, int dim2) {
        if (dim1 <= 0 || dim2 <= 0) {
            printf("invalid dimensions: %d,%d\n", dim1, dim2);
            exit(1);
        }
        int **matrix = calloc(dim1, sizeof(int *));
        if (!matrix) {
            printf("allocation failed\n");
            exit(1);
        }
        for (int i = 0; i < dim1; i++) {
            matrix[i] = calloc(dim2, sizeof(int));
            if (!matrix[i]) {
                printf("allocation failed\n");
                exit(1);
            }
        }
        return matrix;
    }
    
    int **createMatrix(int dim1, int dim2) {
        int **matrix = allocateMatrix(dim1, dim2);
    
        for (int i = 0; i < dim1; i++) {
            for (int j = 0; j < dim2; j++) {
                printf("enter (%d,%d): ", i, j);
                if (scanf("%d", &matrix[i][j]) != 1) {
                    printf("invalid input\n");
                    exit(1);
                }
                //printf("%d\n", matrix[i][j]);
            }
        }
        return matrix;
    }
    
    void deleteMatrix(int **matrix, int dim1) {
        if (matrix == NULL)
            return;
        for (int i = 0; i < dim1; i++) {
            free(matrix[i]);
        }
        free(matrix);
    }
    
    void displayMatrix(int **matrix, int dim1, int dim2) {
        if (matrix == NULL)
            return;
        for (int i = 0; i < dim1; i++) {
            for (int j = 0; j < dim2; j++) {
                printf("[%d]", matrix[i][j]);
            }
            printf("\n");
        }
    }
    
    int **multiply(int **matrix1, int **matrix2, int dim11, int dim12, int dim22) {
        if (matrix1 == NULL || matrix2 == NULL)
            return NULL;
        int **matrix3 = allocateMatrix(dim11, dim22);
        for (int i = 0; i < dim11; i++) {
            for (int j = 0; j < dim22; j++) {
                int cij = 0;
                for (int k = 0; k < dim12; k++) {
                    cij += matrix1[i][k] * matrix2[k][j];
                }
                matrix3[i][j] = cij;
            }
        }
        return matrix3;
    }
    

    请注意,将维度和数据存储到 Matrix 结构以下是使用此方法的修改版本:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Matrix {
        int dim1, dim2;
        int **data;
    } Matrix;
    
    Matrix *matrix_allocate(int rows, int cols);
    Matrix *matrix_input(void);
    void matrix_delete(Matrix *matrix);
    void matrix_display(Matrix *matrix);
    Matrix *matrix_multiply(Matrix *mat1, Matrix *mat2);
    
    int main(void) {
        Matrix *matrix1 = matrix_input();
        if (!matrix1)
            return 1;
        printf("matrix1:\n");
        matrix_display(matrix1);
    
        Matrix *matrix2 = matrix_input();
        if (!matrix2)
            return 1;
        printf("matrix2:\n");
        matrix_display(matrix2);
    
        if (matrix1->dim2 != matrix2->dim1) {
            printf("cannot compute the product of these matrices: dimensions do not match\n");
            matrix_delete(matrix1);
            matrix_delete(matrix2);
            return 1;
        } else {
            Matrix *matrix3 = matrix_multiply(matrix1, matrix2);
            if (!matrix3)
                return 1;
            printf("matrix3:\n");
            matrix_display(matrix3);
            matrix_delete(matrix3);
            matrix_delete(matrix1);
            matrix_delete(matrix2);
            return 0;
        }
    }
    
    Matrix *matrix_allocate(int dim1, int dim2) {
        if (dim1 <= 0 || dim2 <= 0) {
            printf("invalid dimensions: %d,%d\n", dim1, dim2);
            return NULL;
        }
        Matrix *matrix = calloc(1, sizeof(Matrix));
        if (!matrix)
            return NULL;
        matrix->dim1 = dim1;
        matrix->dim2 = dim2;
        matrix->data = calloc(dim1, sizeof(int *));
        if (!matrix->data) {
            printf("allocation failed\n");
            free(matrix);
            return NULL;
        }
        for (int i = 0; i < dim1; i++) {
            matrix->data[i] = calloc(dim2, sizeof(int));
            if (!matrix->data[i]) {
                printf("allocation failed\n");
                while (i-- > 0) {
                    free(matrix->data[i]);
                }
                free(matrix->data);
                free(matrix);
                return NULL;
            }
        }
        return matrix;
    }
    
    void matrix_delete(Matrix *matrix) {
        if (matrix != NULL) {
            for (int i = 0; i < matrix->dim1; i++) {
                free(matrix->data[i]);
            }
            free(matrix->data);
            free(matrix);
        }
    }
    
    Matrix *matrix_input(void) {
        int dim1, dim2;
        printf("enter dim 1: ");
        if (scanf("%d", &dim1) != 1) {
            printf("invalid input\n");
            return NULL;
        }
        printf("enter dim 2: ");
        if (scanf("%d", &dim2) != 1) {
            printf("invalid input\n");
            return NULL;
        }
        Matrix *matrix = matrix_allocate(dim1, dim2);
        if (!matrix)
            return NULL;
        for (int i = 0; i < dim1; i++) {
            for (int j = 0; j < dim2; j++) {
                printf("enter (%d,%d): ", i, j);
                if (scanf("%d", &matrix->data[i][j]) != 1) {
                    printf("invalid input\n");
                    matrix_delete(matrix);
                    return NULL;
                }
            }
        }
        return matrix;
    }
    
    void matrix_display(Matrix *matrix) {
        if (matrix == NULL)
            return;
        for (int i = 0; i < matrix->dim1; i++) {
            for (int j = 0; j < matrix->dim2; j++) {
                printf("[%d]", matrix->data[i][j]);
            }
            printf("\n");
        }
    }
    
    Matrix *matrix_multiply(Matrix *matrix1, Matrix *matrix2) {
        if (matrix1 == NULL || matrix2 == NULL || matrix1->dim2 != matrix2->dim1)
            return NULL;
        Matrix *matrix3 = matrix_allocate(matrix1->dim1, matrix2->dim2);
        if (!matrix3)
            return NULL;
        for (int i = 0; i < matrix1->dim1; i++) {
            for (int j = 0; j < matrix2->dim2; j++) {
                int cij = 0;
                for (int k = 0; k < matrix1->dim2; k++) {
                    cij += matrix1->data[i][k] * matrix2->data[k][j];
                }
                matrix3->data[i][j] = cij;
            }
        }
        return matrix3;
    }