while循环中使用scanf读取字符串触发Segmentation fault问题咨询
问题原因
- 核心诱因是输入缓冲区残留的换行符导致
scanf匹配失败,后续访问未初始化的野指针触发段错误,具体执行逻辑如下:
%[^\n]格式符的匹配规则为读取所有非换行符的字符,遇到换行符就终止匹配,且不会将换行符从输入缓冲区中移除。第一次输入内容按下回车后,缓冲区会残留\n字符。- 第二次进入循环执行
scanf时,读取到的第一个字符就是残留的\n,%[^\n]直接匹配失败,此时scanf返回值为0,不会为buffer分配任何内存,buffer为未初始化的野指针。 - 后续直接执行
printf("%s", buffer)访问野指针,直接触发段错误;同时匹配失败的场景下调用free(buffer)释放野指针也属于非法操作,同样可能引发崩溃。
修复方案
需要同时做三处修改:
- 初始化
buffer为NULL,避免出现不确定的野指针 - 检查
scanf的返回值,只有返回值为1(代表成功匹配1个参数)时,才操作buffer和释放内存 - 处理输入缓冲区残留的换行符,可以在
%m[^\n]前加空格,让scanf自动跳过所有前置空白字符(包括换行符、空格、制表符等)
修复后的参考代码如下:
#include <stdio.h> #include <stdlib.h> int main(){ while(1){ char* buffer = NULL; printf("inserisca una stringa \n"); // 格式符前加空格跳过前置空白,同时校验读取结果 if (scanf(" %m[^\n]", &buffer) == 1) { printf("%s\n", buffer); free(buffer); } else { // 异常场景清空输入缓冲区 while(getchar() != '\n'); } fflush(stdout); } return 0; }
注意:
%m是POSIX标准扩展的scanf格式符,不属于C标准语法,仅在支持POSIX标准的编译环境下可用。
内容的提问来源于stack exchange,提问作者Lorenzo Ferretti
相关产品推荐
相关产品推荐

