C语言命令行传参后fopen返回NULL 原交互输入程序运行正常
fopen 返回 NULL 的排查与修复
两个版本的文件打开逻辑完全没有改动,fopen(square_location,"r")行代码完全一致,出现NULL返回值和新增的命令行参数校验逻辑没有直接关联。
- C语言中用相对路径打开文件时,程序的查找基准是进程启动时的当前工作目录,不是源码存放路径、也不是编译生成的可执行文件的存放路径。
- 原版程序能正常读文件,是因为当时你在存放
square.txt的目录下启动终端、运行编译好的程序;修改代码重新编译后,如果换了路径启动终端、或者直接在IDE里点运行按钮(很多IDE默认的工作目录是项目根目录,不是存放txt的输出目录),就会因为当前目录下找不到square.txt,导致fopen返回NULL。
快速验证与解决方案
- 在运行修改版程序的同一个终端窗口下,执行列目录命令:Windows cmd下输入
dir,PowerShell/Linux/macOS下输入ls,查看当前路径下的文件列表,如果列表中没有square.txt,即可确认是工作目录路径不匹配的问题。 - 修复可以二选一:
- 把
square.txt复制到当前终端所在的工作目录下再运行程序 - 将代码中的路径常量改为txt文件的绝对路径,比如把
#define square_location "square.txt"替换为文件的全路径,绕开相对路径的查找逻辑
- 把
代码中附带的潜在问题(作业提交前建议修复)
排除文件读取的问题后,现有逻辑还存在会导致运行异常的隐藏bug:
- 数组越界风险:连续3个同值的判断逻辑里,行检测的循环条件为
j<MAX,当j取最后两个合法值时,square[i][j+2]会访问到数组索引5的位置(超出0-4的合法索引范围);同理列检测的循环中,i取最后两个值时,会访问到square[5][j]的越界位置。这类越界访问会触发未定义行为,偶现程序崩溃、数值判断错误的问题。修复方式是把行检测的j循环上限改为j <= MAX-3,列检测的i循环上限改为i <= MAX-3。 - 参数解析健壮性不足:当前直接用
sscanf(argv[1], "%d", &c)读取命令行参数时,没有判断解析结果,如果用户传入的参数不是整数,c会保留栈上的随机值,后续的序列匹配结果会完全不可控。可以增加sscanf返回值判断:如果返回值不等于1,直接提示参数格式错误后退出。
内容的提问来源于stack exchange,提问作者Jorge Ávila Balmaceda
相关产品推荐
相关产品推荐

