使用errx()正确终止程序遇异常:printf在errx调用后仍执行
调用errx()后printf仍执行的原因分析
问题代码
#include <stdio.h> #include <err.h> int main(){ printf("\nEnter an integer: "); int age; if(age){ scanf("%d", &age); printf("\nEnter a real number: "); float percent; scanf("%f", &percent); if(percent){ printf("\nEnter an integer: "); int semesters; scanf("%d", &semesters); if(semesters){ printf("\nHenry wanted to be a TA since he was %d years old!\nLittle did he know that he would sacrifice %.2f%% percent of his day.\nSo Henry quit suddenly after %d semesters as a TA...\n", age, percent, semesters); errx(0,"\nProgram was completed without errors"); } else{ errx(1,"Error reading input"); } } else{ errx(1, "Error reading input"); } } else{ errx(1,"Error reading input"); }
现象核心原因拆解
1. 变量未初始化就判断,逻辑完全错误
代码中age、percent、semesters都是局部变量,定义后未初始化就直接用if(变量)做判断,这些变量的初始值是内存中的随机垃圾值,完全不可控。
当输入[时,scanf("%d", &age)会因为输入格式不匹配读取失败,返回0,但age的数值还是随机的。此时if(age)的结果全靠运气:
- 若随机值非0,程序会继续执行后续的
printf("\nEnter a real number: "),之后才可能因为percent的随机值进入错误分支调用errx; - 若随机值为0,才会直接触发第一个错误分支调用
errx。
这就是为什么会出现“程序终止后仍有printf内容输出”的根本逻辑错误——你根本没在输入失败时立即终止程序,而是靠随机变量值决定流程。
正确的做法是判断scanf的返回值:
// 读取整数时,成功则返回1,失败返回0或EOF if(scanf("%d", &age) != 1) { errx(1, "Error reading input"); }
2. 标准IO缓冲机制导致输出顺序混乱
printf输出到stdout,默认是行缓冲模式:只有输出换行符、缓冲区满,或者程序正常退出时,才会把缓冲区内容刷到屏幕。而errx的错误信息输出到stderr,stderr是无缓冲的,内容会立即显示。
当errx调用exit终止程序时,exit会自动刷新stdout的缓冲区。这就导致之前printf留在缓冲区的内容(比如Enter a real number: )会在错误信息之前或之后被刷出,看起来像是errx执行后printf才输出,但实际是缓冲区延迟刷新的视觉错觉。
如果要让printf内容立即显示,可在printf后调用fflush(stdout);强制刷新缓冲区。
内容的提问来源于stack exchange,提问作者Haidari
相关产品推荐
相关产品推荐

