C语言密码校验代码为何运行时会出现CPU占用过高问题?
问题说明
C语言初学者完成密码校验代码补全练习:程序需要提示用户输入密码,输入内容匹配password1时输出密码正确提示。写出的代码手动运行符合功能预期,但被练习平台自动评分系统判定CPU占用过高,初步怀疑问题与feof的检查逻辑有关,需要定位问题根源。
原问题代码如下:
#include <stdio.h> #include <string.h> #define MAX_BUFFER_SIZE 80 /* Prompts user for password, waits for correct password */ void wait_for_correct_password(void) { char buffer[MAX_BUFFER_SIZE]; printf("Enter password: "); char* password = fgets(buffer, MAX_BUFFER_SIZE, stdin); // Write your while loop here while (!feof(stdin)){ while (strcmp(password, "password1\n" )!=0 ) { fgets(buffer, MAX_BUFFER_SIZE, stdin); } printf("Password correct!\n"); break; } } int main(int argc, char** argv){ wait_for_correct_password(); }
问题根源
CPU占用过高的核心原因是代码存在无阻塞的死循环,和feof的错误用法直接相关:
- 内层循环完全没有检查
fgets的返回值:当输入流到达EOF(比如平台自动化测试用重定向输入做校验,输入完测试用例后流就关闭了),后续所有fgets调用都会立刻返回NULL,不会阻塞等待新输入,buffer里留存的还是上一次读到的错误密码内容,strcmp永远返回非0值,内层循环会无间断反复执行字符串比较,完全不触发IO阻塞,直接把CPU核心跑满。 feof用法完全错误:feof的作用是IO操作已经返回失败后,用来判断失败原因是否为到达文件末尾,不能用来作为循环入口的读前置判断。原代码只在外层循环做了一次feof检查,内层循环既不判断流状态,也不判断fgets返回值,一旦fgets读失败,不管是EOF还是流错误,都会直接触发内层无限空转。- 循环逻辑冗余:外层循环执行一次就直接
break,完全没有循环存在的意义,两层嵌套的结构反而放大了逻辑漏洞。
修复方案
修复时要遵循两个原则:一是所有IO调用都要直接检查返回值,读失败立刻退出循环避免空转;二是不要用feof作为循环的判断条件。
修复后的代码如下:
#include <stdio.h> #include <string.h> #define MAX_BUFFER_SIZE 80 /* Prompts user for password, waits for correct password */ void wait_for_correct_password(void) { char buffer[MAX_BUFFER_SIZE]; printf("Enter password: "); // 每次读入直接检查fgets返回值,读失败(NULL)直接退出,不会空转 while (fgets(buffer, MAX_BUFFER_SIZE, stdin) != NULL) { if (strcmp(buffer, "password1\n") == 0) { printf("Password correct!\n"); return; } } } int main(int argc, char** argv){ wait_for_correct_password(); return 0; }
修复后不会出现CPU占用过高的问题:当等待用户输入时,fgets会阻塞挂起进程,不会消耗CPU资源;一旦输入流结束或出错,fgets返回NULL,循环直接退出,不会出现无限空跑的逻辑。
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

