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

C语言实现凯撒密码调用encrypt函数触发Segmentation Fault报错

问题描述

开发凯撒密码程序时,使用密钥1、明文输入hello.运行程序,触发Segmentation fault (core dumped)报错。已知该错误为程序访问非法内存位置导致,且触发于encrypt函数调用流程中,无法定位具体出错点。
调试过程中捕获的报错状态截图

原始代码
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

bool isValidKey(string);
string encrypt(string, int);

string c;

int main(int argc, string argv[])
{
    if (argc != 2 || isValidKey(argv[1]) == 0)
    {
        printf("Useage: ./caesar key\n");
        return 0;
    }
    string p = get_string("plaintext: ");
    c = encrypt(p, atoi(argv[1]));
    printf("%s", c);
    return 0;
}

bool isValidKey(string key)
{
    for (int i = 0; i < strlen(key); i++)
    {
        if (isdigit(key[i]) == 0)
        {
            return false;
        }
    }
    return true;
}

string encrypt(string plain, int k)
{
    for (int i = 0; i < strlen(plain); i++)
    {
        if (isalpha(plain[i]) != 0)
        {
            if (islower(plain[i]) != 0)
            {
                c[i] = ((plain[i] - 97 + k) % 26) + 97;
            }
            else
            {
                c[i] = ((plain[i] - 65 + k) % 26) + 65;
            }
        }
    }
    return c;
}
故障原因
  • 段错误直接诱因:全局变量c是char*类型指针,声明后未分配任何有效可读写内存,属于野指针。在encrypt函数中直接对c[i]执行赋值操作,是向非法内存地址写入数据,必然触发段错误。
  • 逻辑缺陷:加密流程未处理非字母字符,输入的.、标点、空格等内容不会被写入密文,即使修复内存问题,也会因为密文字符串缺少结束符、内容不完整导致输出乱码或越界读取。
  • 细节问题:参数校验失败时返回0不符合POSIX命令行规范,命令执行出错应返回非0退出码;提示信息存在拼写错误(Useage应为Usage)。
修复后代码
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

bool isValidKey(string);
string encrypt(string, int);

int main(int argc, string argv[])
{
    if (argc != 2 || isValidKey(argv[1]) == 0)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    string p = get_string("plaintext: ");
    string c = encrypt(p, atoi(argv[1]));
    printf("ciphertext: %s\n", c);
    free(c);
    return 0;
}

bool isValidKey(string key)
{
    for (int i = 0, len = strlen(key); i < len; i++)
    {
        if (!isdigit(key[i]))
        {
            return false;
        }
    }
    return true;
}

string encrypt(string plain, int k)
{
    int len = strlen(plain);
    // 申请与明文长度匹配的内存,额外1字节存字符串结束符
    string cipher = malloc(len + 1);
    for (int i = 0; i < len; i++)
    {
        if (isalpha(plain[i]))
        {
            if (islower(plain[i]))
            {
                cipher[i] = ((plain[i] - 'a' + k) % 26) + 'a';
            }
            else
            {
                cipher[i] = ((plain[i] - 'A' + k) % 26) + 'A';
            }
        }
        else
        {
            // 非字母字符直接原样保留
            cipher[i] = plain[i];
        }
    }
    // 补字符串结束标记
    cipher[len] = '\0';
    return cipher;
}
修复说明
  • 移除无意义的全局密文指针,在encrypt函数内通过malloc申请对应大小的堆内存,从根源解决野指针问题。
  • 遍历明文时对非字母字符做原样复制,遍历结束后强制在密文末尾写入\0结束符,保证字符串格式合法。
  • 优化循环逻辑,提前计算字符串长度,避免循环每次执行都调用strlen降低效率。
  • 修正拼写错误与退出码问题,使用'a'/'A'字符字面量替换硬编码的ASCII值,提升代码可读性。
  • 密文使用完成后调用free释放申请的堆内存,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:03:22