matrizdinamica.c本地运行正常,提交系统报Segmentation Fault及退出状态错误
问题排查:动态矩阵程序段错误与退出状态异常
需求概述
编写matrizdinamica.c程序,实现以下功能:
- 创建
m×n的long int类型矩阵,m和n通过命令行参数argv[1]、argv[2]传入 - 矩阵元素生成规则:
- 第1行所有元素为1
- 第1列所有元素为1
- 其余元素
x[i][j] = x[i-1][j] + x[i][j-1],若结果大于10^6则设为1
- 矩阵按行输出,每行以
\n结尾,元素用%li\t格式,最后一列用%li\n格式 - 内存分配失败时无输出,返回状态码71;正常运行返回0,终止前释放所有内存
问题现象
本地运行./matrizdinamica 4 5可得到预期输出,编译命令为gcc -ansi -pedantic -Wall -Wextra -Werror matrizdinamica matrizdinamica.c,但提交至教师评测系统时,提示Segmentation Fault (Core Dumped),且退出状态不正确。
现有代码
#include <stdlib.h> #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { int filas = strtol(argv[1], NULL, 10); int columnas = strtol(argv[2], NULL, 10); long int **x; int i; /* Recorre filas*/ int j; /* Recorre columnas */ /*Reserva de Memoria*/ x = (long int **) malloc (filas*sizeof(long int*)); if(x==NULL){ printf("Error: outta memory"); exit(71); } for (i=0;i<filas;i++){ x[i] = (long int*)malloc(columnas*sizeof(long int)); if (x[i]==NULL) { exit(71); } } /* Damos Valores a la Matriz*/ for (i=0; i<filas; i++){ for (j=0; j<columnas; j++){ if(i==0) x[i][j]=1; else if (j==0) x[i][j]=1; else { x[i][j]=x[i-1][j]+x[i][j-1]; if (x[i][j]>1000000) x[i][j]=1; } } } /* Dibujamos la Matriz en pantalla */ for (i=0; i<filas; i++){ /*printf("\n");*/ for (j=0; j<columnas; j++){ if (j==columnas-1){ printf("%li\n", x[i][j]); } else { printf("%li\t", x[i][j]); } } } /* if (i < filas -1){ printf("\n");} }*/ /*printf("\n");*/ for(i = 0; i < filas; i++){ free(x[i]); } /* free(x);*/ return 0; }
问题根源分析
命令行参数未校验
- 未检查
argc是否等于3,若用户未传入足够参数,argv[1]或argv[2]为NULL,调用strtol会直接触发段错误 - 未校验
strtol转换结果,若传入非数字参数,filas或columnas会被设为0,后续malloc(0)返回的指针使用时会引发段错误
- 未检查
内存分配失败处理不符合要求
- 内存分配失败时代码打印了错误信息,但需求明确要求无输出,导致评测系统判定输出异常
- 循环中某一行分配失败时,直接
exit(71)未释放已分配的前序行内存,同时顶层指针x也未释放(代码中注释掉了free(x)),违反内存释放要求
类型匹配错误
strtol返回long类型,直接赋值给int类型的filas和columnas,若传入数值超过int范围会导致溢出,引发后续内存分配或数组越界问题
修复方案
1. 补充命令行参数校验
#include <limits.h> // 需引入此头文件获取INT_MAX // 检查参数数量 if (argc != 3) { exit(71); } char *endptr1, *endptr2; long filas_long = strtol(argv[1], &endptr1, 10); long columnas_long = strtol(argv[2], &endptr2, 10); // 校验转换有效性与数值范围 if (endptr1 == argv[1] || filas_long <= 0 || filas_long > INT_MAX) { exit(71); } if (endptr2 == argv[2] || columnas_long <= 0 || columnas_long > INT_MAX) { exit(71); } int filas = (int)filas_long; int columnas = (int)columnas_long;
2. 修正内存分配失败处理
x = malloc(filas * sizeof(long int*)); // C中无需强制转换malloc返回值 if (x == NULL) { exit(71); } for (i = 0; i < filas; i++) { x[i] = malloc(columnas * sizeof(long int)); if (x[i] == NULL) { // 释放已分配的所有行 for (int k = 0; k < i; k++) { free(x[k]); } free(x); exit(71); } }
3. 恢复顶层指针释放
取消free(x);的注释,确保所有内存被释放:
for(i = 0; i < filas; i++){ free(x[i]); } free(x); // 恢复此语句
4. 移除错误打印语句
删除内存分配失败时的printf("Error: outta memory");,符合无输出要求。
内容的提问来源于stack exchange,提问作者Miguel Ángel
相关产品推荐
相关产品推荐

