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

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校验逻辑位置错误,是触发段错误的核心原因:

  1. 进入main函数后,你第一行就执行string key = argv[1];。当用户不传入第二个参数时,argv数组仅argv[0](程序自身路径)有效,argv[1]是空指针,没有指向合法的字符串内存。
  2. 紧接着你进入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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:12:53