CS50程序未传命令行参数时触发Segmentation fault (core dumped)报错
CS50替换加密程序无参数运行触发段错误问题
问题背景
我正在编写CS50课程的替换加密程序,预期通过用户在命令行传入的密钥对消息进行加密。程序需要对传入的密钥做多维度合法性校验,命令行参数非法时直接返回状态码终止运行。
目前程序仅完成命令行输入校验逻辑,代码如下:
#include <cs50.h> #include <stdio.h> #include <string.h> #include <ctype.h> int char_repeat(string key); int key_check(string key); int main(int argc, string argv[]) { string key = argv[1]; for (int i = 0; i < strlen(key); i++) { char c = toupper(key[i]); // 校验密钥合法性 if (argc < 2 || strlen(key) != 26 || c < 65 || c > 90) { printf("Usage: ./substitution key\n"); return 1; } } char_repeat(key); printf("this should not print if invalid..."); return 0; } int char_repeat(string key) { // 检查密钥是否有重复字符 for (int i = 0; i < strlen(key); i++) { for (int j = i + 1; j < strlen(key); j++) { if (toupper(key[i]) == toupper(key[j])) { printf("Usage: ./substitution key\n"); return 1; } } } printf("this should not print if invalid..."); return 0; }
测试现象
传入以下非法参数测试时,程序均可正常输出使用提示Usage: ./substitution key,不会打印调试语句this should not print if invalid...:
./sub AB*DEFGHIJKLMNOPQRSTUVWXYZ./sub ABC./sub ABCABCABCABCABCABCABCABCAB./sub ABCDEFGHIJKLMNOPQRSTUVWXYZ-
但直接运行程序不传入第二个参数,即执行./sub时,程序不会输出预期提示,直接触发段错误:
segmentation fault (core dumped)
我已经在if判断中加入了argc < 2的校验逻辑,按理应该和其他非法场景一致输出使用提示。我了解段错误属于访问非法内存类错误,但不清楚该问题和当前代码的关联,怀疑是return语句使用存在问题。
根因分析
你的argc < 2校验逻辑位置错误,是触发段错误的核心原因:
- 进入main函数后,你第一行就执行
string key = argv[1];。当用户不传入第二个参数时,argv数组仅argv[0](程序自身路径)有效,argv[1]是空指针,没有指向合法的字符串内存。 - 紧接着你进入for循环,循环条件会第一时间执行
strlen(key),相当于直接读取空指针指向的非法内存,当场触发段错误——此时程序还没走到循环内部的if (argc < 2)判断分支,自然不会输出预期的提示信息。
另外代码还有一个隐藏逻辑漏洞:调用char_repeat(key)时没有接收返回值,就算函数检测到重复字符返回1,main函数还是会继续向下执行,打印后续的调试语句,不符合校验不通过就终止的设计预期。
修复方案
按照校验优先级调整逻辑顺序,先做不需要访问argv[1]的参数个数校验,再依次做密钥长度、字符合法性、重复字符校验,同时正确处理校验函数的返回值:
int main(int argc, string argv[]) { // 优先校验参数个数,不合法直接退出 if (argc != 2) { printf("Usage: ./substitution key\n"); return 1; } string key = argv[1]; // 校验密钥长度 if (strlen(key) != 26) { printf("Usage: ./substitution key\n"); return 1; } // 逐字符校验是否全为字母 for (int i = 0; i < 26; i++) { if (!isalpha(key[i])) { printf("Usage: ./substitution key\n"); return 1; } } // 校验重复字符,检测到非法直接退出 if (char_repeat(key) == 1) { return 1; } // 校验通过后再执行后续加密逻辑 printf("Key validation passed\n"); return 0; }
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

