You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言矩阵乘积程序输入阶段崩溃问题求助

矩阵乘积C程序输入阶段崩溃的排查与修复

问题描述

实现了一个基于动态内存分配的矩阵乘积C程序,但在输入矩阵元素过程中提前终止崩溃,测试输入到Digite o elemento 2x1 da matriz 1: 3时程序崩溃。

完整程序代码

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

int **alloc_matrix(size_t l, size_t c) {
    int **matrix = (int**) calloc(c,sizeof(int));

    for (size_t i = 0; i < c; i++){
        matrix[i] = (int*) calloc(l,sizeof(int));
    }
     
    return matrix;
}

void liberaMatriz(int **M, int n){
    for (int i = 0; i < n; i++) free(M[i]);
    free(M);
}

int** multiplicaM(int **A, int l1, int c1, int **B, int l2, int c2) {
    int **matrix_res = alloc_matrix(l1, c2);

    if (c1 != l2) {
        return NULL;
    }

    for (int i = 0; i < l1; i++) {
        for (int j = 0; j < c2; j++) {
            for (int k = 0; k < c1; k++) {
                matrix_res[i][j] += A[i][k] * B[j][k];        
            }
        }
    }
    
    return matrix_res;
}


int main(){
    int linhas1, colunas1, linhas2, colunas2;

    printf("Digite o numero de linhas da matriz A: ");
    scanf("%d", &linhas1);
    printf("Digite o numero de colunas da matriz A: ");
    scanf("%d", &colunas1);

    printf("Digite o numero de linhas da matriz B: ");
    scanf("%d", &linhas2);
    printf("Digite o numero de colunas da matriz B: ");
    scanf("%d", &colunas2);

    int **matrix1 = alloc_matrix(linhas1,colunas1);
    int **matrix2 = alloc_matrix(linhas2,colunas2);

    for (int i = 0; i < linhas1; i++) {
        for (int j = 0; j < colunas1; j++) {
            printf("Digite o elemento %dx%d da matriz 1: ", i+1, j+1);
            scanf("%d", &matrix1[i][j]);
        }   
    }

    for (int i = 0; i < linhas2; i++) {
        for (int j = 0; j < colunas2; j++) {
            printf("Digite o elemento %dx%d da matriz 2: ", i+1, j+1);
            scanf("%d", &matrix2[i][j]);
        }   
    }

    int **matrix3 = multiplicaM(matrix1, linhas1, colunas1, matrix2, linhas2, colunas2);

    if (matrix3 != NULL) {
        printf("Matriz Resultado: \n");
        for (int i = 0; i < linhas1; i++) {
            for (int j = 0; j < colunas2; j++) {
                printf("%d ", matrix3[i][j]);
            }
            printf("\n");
        }
    }
    
    liberaMatriz(matrix1, linhas1);
    liberaMatriz(matrix2, linhas2);
    liberaMatriz(matrix3, linhas1);
    
return 0;
}

测试输入

Digite o numero de linhas da matriz A: 3
Digite o numero de colunas da matriz A: 1
Digite o numero de linhas da matriz B: 1
Digite o numero de colunas da matriz B: 3
Digite o elemento 1x1 da matriz 1: 2
Digite o elemento 2x1 da matriz 1: 3

崩溃核心原因

1. alloc_matrix内存分配类型错误

函数中int **matrix = (int**) calloc(c,sizeof(int));存在致命错误:

  • 要分配的是c个int*指针的内存,但实际只分配了c个int的内存空间。在64位系统中,int*占8字节,int占4字节,内存空间不足会导致后续指针赋值操作越界,破坏堆结构,最终触发段错误。

2. 矩阵存储逻辑与访问逻辑不匹配

alloc_matrix的循环是遍历c次(列数),为每个列分配l个int的内存,属于列优先存储;但后续输入和计算代码中,matrix1[i][j]是按行优先访问(i是行索引,j是列索引)。

  • 以测试输入的3行1列矩阵A为例,alloc_matrix(3,1)只分配了1个指针,对应1列的3个元素。输入代码中i遍历到第2行时,访问matrix1[1][0]会指向未分配的内存地址,直接触发崩溃。

3. 其他潜在问题

  • multiplicaM先分配结果矩阵再判断维度合法性,会导致内存泄漏;
  • 矩阵乘法计算错误:B[j][k]应为B[k][j],不符合矩阵行乘列的规则;
  • liberaMatriz释放逻辑与存储逻辑不匹配,且未处理空指针情况。

修复方案

1. 修正alloc_matrix(改为行优先存储,增加内存检查)

int **alloc_matrix(size_t rows, size_t cols) {
    int **matrix = (int**) calloc(rows, sizeof(int*));
    if (matrix == NULL) return NULL;

    for (size_t i = 0; i < rows; i++){
        matrix[i] = (int*) calloc(cols, sizeof(int));
        if (matrix[i] == NULL) {
            // 分配失败时回滚已分配内存
            for (size_t j = 0; j < i; j++) free(matrix[j]);
            free(matrix);
            return NULL;
        }
    }
    return matrix;
}

2. 修正multiplicaM(先判维度再分配内存,修正乘法索引)

int** multiplicaM(int **A, int l1, int c1, int **B, int l2, int c2) {
    if (c1 != l2) return NULL;

    int **matrix_res = alloc_matrix(l1, c2);
    if (matrix_res == NULL) return NULL;

    for (int i = 0; i < l1; i++) {
        for (int j = 0; j < c2; j++) {
            int sum = 0;
            for (int k = 0; k < c1; k++) {
                sum += A[i][k] * B[k][j];
            }
            matrix_res[i][j] = sum;
        }
    }
    return matrix_res;
}

3. 修正liberaMatriz(处理空指针,匹配行优先逻辑)

void liberaMatriz(int **M, int rows){
    if (M == NULL) return;
    for (int i = 0; i < rows; i++) {
        if (M[i] != NULL) free(M[i]);
    }
    free(M);
}

4. 修正main函数的内存释放逻辑

// ... 原有代码 ...
if (matrix3 != NULL) {
    printf("Matriz Resultado: \n");
    for (int i = 0; i < linhas1; i++) {
        for (int j = 0; j < colunas2; j++) {
            printf("%d ", matrix3[i][j]);
        }
        printf("\n");
    }
    liberaMatriz(matrix3, linhas1);
}

liberaMatriz(matrix1, linhas1);
liberaMatriz(matrix2, linhas2);
// ... 原有代码 ...

内容的提问来源于stack exchange,提问作者Lfeikb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 22:35:55