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

C语言inputCString函数运行时错误(缓冲区溢出)求助

inputCString函数缓冲区溢出导致运行时错误排查与修复

问题描述

我编写了一个inputCString函数,用于获取长度符合指定范围的C字符串输入。配合测试用例运行时,程序虽能执行但终端会弹出运行时错误提示,关闭提示后程序才可继续运行。怀疑是函数内字符串赋值导致缓冲区溢出,但无法定位具体问题。

测试用例代码

void test06_inputCString(void) {
char cstringValue[7] = { '\0' };

// Test explicit string length
printf("TEST #6: - Instructions:\n"
       "1) Enter the word 'horse'   [ENTER]\n"  // too short
       "2) Enter the word 'chicken' [ENTER]\n"  // too long
       "3) Enter the word 'SENECA'  [ENTER]\n"  // just right
       ":>");

// You may want to comment the next line if you have not yet created the inputCString function:
inputCString(cstringValue, 6, 6);

printf("////////////////////////////////////////\n");
printf("TEST #6 RESULT: ");
printf("%s (expected result: SENECA)\n", cstringValue);
printf("////////////////////////////////////////\n\n");}

我的inputCString函数源码

void inputCString(char* str, int minChar, int maxChar){
int i = 0, valid = 0;

while (valid != 1)
{
    scanf(" %[^\n]", str);
    int len = 0;
    for (i = 0; str[i] != '\0'; i++)
    {
        len++;
    }
    str[len] = '\0'; // Replace newline with null terminator

    if (len >= minChar && len <= maxChar)
    {
        valid = 1;
    }
    else
    {
        if (minChar == maxChar)
        {
            printf("ERROR: String length must be exactly %d chars: ", minChar);
        }
        else
        {
            if (len < minChar || len > maxChar)
            {
                printf("Error: String length must be between %d and %d chars: ", minChar, maxChar);
            }
        }
    }
}

函数要求

该函数用于获取长度在第2、3个参数指定范围内(包含边界值)的C字符串输入:

  • 必须接收3个参数:第1个为指向C字符串的字符指针(假定大小至少容纳上限长度);第2个为输入最小长度;第3个为输入最大长度
  • 无返回值,通过第1个参数指针返回C字符串
  • 验证输入长度,不符合则显示对应错误信息;若最小、最大长度相同,输入必须为该指定长度
  • 持续提示输入直到符合要求,确保返回字符串长度在指定范围内

错误与预期情况

  • 错误信息:终端弹出缓冲区溢出检测提示,程序暂停运行,需关闭提示才能继续。
  • 预期输出:按照测试步骤输入后,最终输出SENECA (expected result: SENECA),符合长度要求的输入被正确接收。

问题根源

  1. 无限制的scanf输入:scanf(" %[^\n]", str)未指定最大读取长度,当输入字符数超过缓冲区容量时,会直接写入缓冲区之外的内存,触发溢出检测。比如测试中输入"chicken"(7个字符),而缓冲区cstringValue大小为7,需留1个位置存'\0',最多只能存6个字符,输入7个就会溢出。
  2. 冗余且危险的赋值:str[len] = '\0'完全多余,因为循环已遍历到字符串的'\0'终止符位置,此时str[len]本身就是'\0';若输入溢出导致'\0'被覆盖,len可能超出缓冲区范围,这行代码会进一步越界写内存。
  3. 手动长度计算的风险:手动循环计算长度时,若字符串未被正确终止(溢出后),会越界访问内存,引发未定义行为。

修正后的函数代码

#include <string.h>

void inputCString(char* str, int minChar, int maxChar){
    int valid = 0;
    char format[20];
    // 构造带长度限制的scanf格式串,确保最多读取maxChar个字符
    sprintf(format, " %%%d[^\n]", maxChar);

    while (!valid)
    {
        // 限制读取长度,避免缓冲区溢出
        scanf(format, str);
        // 清理输入缓冲区中剩余的换行符,防止影响下一次读取
        while (getchar() != '\n');

        int len = strlen(str);

        if (len >= minChar && len <= maxChar)
        {
            valid = 1;
        }
        else
        {
            if (minChar == maxChar)
            {
                printf("ERROR: String length must be exactly %d chars: ", minChar);
            }
            else
            {
                printf("Error: String length must be between %d and %d chars: ", minChar, maxChar);
            }
        }
    }
}

关键修改说明

  • 限制scanf读取长度:通过sprintf构造%maxChar[^\n]格式串,让scanf最多读取maxChar个字符,确保不超出缓冲区容量(符合函数要求中“缓冲区至少容纳上限长度”的前提)。
  • 清理输入缓冲区:每次读取后用while (getchar() != '\n')清空换行符,避免残留字符干扰后续输入。
  • 替换长度计算方式:用strlen代替手动循环,简洁且避免越界风险。
  • 移除冗余赋值:删除str[len] = '\0',因为scanf会自动添加终止符,且strlen依赖'\0'工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 02:35:05