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

使用strlen处理argv[1]时触发Segmentation Fault的问题求助

CS50 Substitution题调试问题:段错误与无限循环

正在学习CS50(首次接触C语言),完成Substitution题目时遇到问题:运行代码陷入无限循环,调试发现调用strlen获取argv[1]长度时触发段错误,调试显示key的值为0x0,怀疑argv[1]未以NULL结尾,但无法确定。

问题代码

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int check(string str);

int main(int argc, string argv[])
{
    if(argc < 1 || argc > 2)
    {
        printf("Usage: ./substitution key");
        return 1;
    }

    string key = argv[1];

    if(check(key) == 1)
    {
            return 1;
    }

    string plaintext = get_string("plaintext:");
    int lenght = strlen(plaintext);
    char ciphertext[lenght + 1];

    for(int i = 0; i <= lenght; i++)
    {
        if(islower(plaintext[i]))
        {
            plaintext[i] -= 97;
            ciphertext[i] = key[(int)plaintext[i]];
            if(isupper(ciphertext[i]))
            {
                ciphertext[i] = tolower(ciphertext[i]);
            }
        }

        if(isupper(plaintext[i]))
        {
            plaintext[i] -= 65;
            ciphertext[i] = key[(int)plaintext[i]];
            if(islower(ciphertext[i]))
            {
                ciphertext[i] = toupper(ciphertext[i]);
            }
        }
    }

    printf("ciphertext:%s", ciphertext);
}

int check(string str)
{
    //检查字符数量、是否重复或包含数字
   char alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
   int count[26] = { 0 };
   if(strlen(str) != 26)
   {
    printf("Key must contain 26 characters.");
    return 1;
   }
   for(int i = 0; i < 25; i++)
   {
        if(isalpha(str[i]) == 0)
        {
            return 1;
        }

        str[i] = (char)tolower(str[i]);

        for(int j = 0; j < 25; j++)
        {
            if(str[i] == alphabet[j])
            {
                count[j] += 1;
            }

        }
    }

    for(int i = 0; i < 25; )
    {
        if(count[i] != 1)
        {
            return 1;
        }
    }

    return 0;
}

调试错误信息

程序收到信号SIGSEGV,段错误。__strlen_evex () 在 ../sysdeps/x86_64/multiarch/strlen-evex.S:77


问题分析与修复

1. 段错误的直接原因:参数判断错误

原代码中if(argc < 1 || argc > 2)的判断逻辑错误:C语言中argc最小值为1(程序自身路径),当用户未输入密钥时,argc=1,此时argv[1]为NULL,调用strlen(NULL)必然触发段错误。

修复:将参数判断改为:

if(argc != 2)
{
    printf("Usage: ./substitution key\n");
    return 1;
}

2. check函数的循环错误

  • 遍历密钥的循环for(int i = 0; i < 25; i++)仅遍历前25个字符,遗漏第26个,应改为i < 26;
  • 内部匹配字母表的循环for(int j = 0; j < 25; j++)同理,改为j < 26;
  • 最后检查count数组的循环for(int i = 0; i < 25; )没有递增i,导致无限循环,且边界错误,应改为for(int i = 0; i < 26; i++)。

3. 加密逻辑的问题

  • 循环条件i <= lenght会越界访问字符串末尾的NULL字符,应改为i < lenght;
  • 修改了原plaintext的内容(plaintext[i] -= 97),破坏输入数据,应使用临时变量存储索引;
  • 未处理非字母字符,导致ciphertext对应位置未赋值,出现乱码;
  • ciphertext未添加终止NULL字符,printf输出时会读取内存垃圾数据。

修正后的完整代码

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int check(string str);

int main(int argc, string argv[])
{
    if(argc != 2)
    {
        printf("Usage: ./substitution key\n");
        return 1;
    }

    string key = argv[1];

    if(check(key) == 1)
    {
        return 1;
    }

    string plaintext = get_string("plaintext: ");
    int length = strlen(plaintext);
    char ciphertext[length + 1];

    for(int i = 0; i < length; i++)
    {
        if(islower(plaintext[i]))
        {
            int idx = plaintext[i] - 'a';
            ciphertext[i] = tolower(key[idx]);
        }
        else if(isupper(plaintext[i]))
        {
            int idx = plaintext[i] - 'A';
            ciphertext[i] = toupper(key[idx]);
        }
        else
        {
            // 非字母字符直接复制
            ciphertext[i] = plaintext[i];
        }
    }
    // 添加字符串终止符
    ciphertext[length] = '\0';

    printf("ciphertext: %s\n", ciphertext);
    return 0;
}

int check(string str)
{
    int count[26] = {0};
    if(strlen(str) != 26)
    {
        printf("Key must contain 26 characters.\n");
        return 1;
    }

    for(int i = 0; i < 26; i++)
    {
        if(!isalpha(str[i]))
        {
            printf("Key must contain only alphabetic characters.\n");
            return 1;
        }

        char lower_char = tolower(str[i]);
        int idx = lower_char - 'a';
        // 检查字符是否重复
        if(count[idx] != 0)
        {
            printf("Key must contain each letter exactly once.\n");
            return 1;
        }
        count[idx]++;
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者gondola

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 01:05:11