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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:37:09