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

