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
相关产品推荐
相关产品推荐

