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

C语言用户输入偶现异常:长输入触发程序崩溃求助

输入长度导致C程序崩溃问题排查

终端运行示例

dennis@MBP2021 Encryption % make
cc Gronsfeld_Cipher.c /Users/dennis/Documents/C/programs/DJSlibrary/cs50.c -o cipher
dennis@MBP2021 Encryption % ./cipher 

Please enter line to be encoded: This, however, is not the time.

You entered: This, however, is not the time. Length: 31

The message is:  This, however, is not the time.
The cipher is:   EZNH, SCVKOHZ, KF UFP GXF ONWX.
The decipher is: THIS, HOWEVER, IS NOT THE TIME.


dennis@MBP2021 Encryption % ./cipher

Please enter line to be encoded: This, however, is not the time, nor the place to have fun.

You entered: This, however, is not the time, nor the place to have fun. Length: 58
zsh: trace trap  ./cipher
dennis@MBP2021 Encryption % 

问题代码片段

char data[] = "Dummy";
int keys[] = {11, 7, 13, 10, 25, 9, 8, 3};  


// Do the stuff
int main(void)
{   
    // Get input from user
    char *string_input = NULL;
    size_t string_size = 250;
    ssize_t bytes_read;

    printf("\nPlease enter line to be encoded: ");
    string_input = (char *) malloc(string_size);
    bytes_read = getline(&string_input, &string_size, stdin);

    if(bytes_read < 2)
    {
        printf("\n\nNo input was entered. Program terminating.\n");
        printf("Error Code: 1\n\n");
        free(string_input);
        return 1; 
    }

    string_input[bytes_read-1] = 0; // Clear out the new line.
    
    printf("\nYou entered: %s Length: %ld\n", string_input, bytes_read-1);
    strcpy(data, string_input);
    free(string_input);

    // Get sizes
    int DataLen = strlen(data);
    int ks = sizeof(keys) / sizeof(keys[0]);

    printf("\nThe message is:  %s", data);

}

问题原因

核心是缓冲区溢出:

  • char data[] = "Dummy";定义的是栈上固定大小数组,长度仅为6(5个字符加字符串结束符\0)。
  • strcpy函数不会检查目标数组的容量,会持续复制直到遇到\0。短输入(31字节)已经超出data的容量,属于未定义行为——只是刚好没破坏栈上关键数据(如返回地址、栈帧指针),所以暂时没崩溃;长输入(58字节)直接覆盖栈上关键数据,触发内存错误导致程序崩溃。

解决方案

有两种安全处理方式:

方式1:直接使用动态分配的string_input

既然getline已经动态分配了足够存储输入的内存,可直接用string_input替代data,省去复制步骤:

// 移除全局的char data[] = "Dummy";

int main(void)
{
    // ... 输入逻辑保持不变 ...

    // 直接使用string_input,无需strcpy
    int DataLen = strlen(string_input);
    int ks = sizeof(keys) / sizeof(keys[0]);

    printf("\nThe message is:  %s", string_input);

    // 最后记得释放内存
    free(string_input);
}

方式2:动态分配data的内存

若必须保留data变量,根据输入长度动态分配内存:

// 将全局的char data[] = "Dummy";改为指针
char *data = NULL;

int main(void)
{
    // ... 输入逻辑保持不变 ...

    // 动态分配足够存储输入的内存
    data = malloc(strlen(string_input) + 1);
    if (data == NULL) {
        printf("内存分配失败.\n");
        free(string_input);
        return 1;
    }
    strcpy(data, string_input);
    free(string_input);

    // ... 后续逻辑保持不变 ...

    // 最后记得释放data的内存
    free(data);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:23:16