调试模式下如何刷新fmt库的实时打印输出?
fmt库调试时无法实时输出的问题解决
问题根因
你遇到的输出延迟问题是两层缓冲叠加导致的,之前的操作没生效是因为没覆盖到所有缓冲层:
- 第一层是fmt库自身的内部输出缓冲:fmt为了提升输出性能,不会每次调用
print就立刻把内容写到系统/C标准库的流里,会先存在自己申请的内存块里,攒够一定量再批量写出。你之前直接调用fflush(stdout)的时候,fmt还没把内容写到C标准库的stdout缓冲区,相当于刷了个空缓冲,自然没有效果。 - 第二层是C标准库的stdout流缓冲:默认情况下,stdout连接到tty终端是行缓冲(遇到
\n刷新),连接到管道/重定向文件是全缓冲(攒够块大小才刷新)。IDE调试时的输出面板本质是通过管道捕获程序的stdout内容,本身就不会按行刷新。你加的setbuf(stdout, NULL)只是关闭了这一层的缓冲,没处理fmt自己的那层,所以跑sleep的时候能看到分段输出,单步调试时还是会因为fmt层的缓冲+IDE按块读管道的机制看不到实时内容。
可行解决方案
按优先级从高到低选择即可:
- 方案1:输出后主动调用fmt自带的刷新接口
不要只用C库的fflush,每次fmt::print之后调用fmt::flush(stdout),这个接口会先把fmt内部缓冲的内容全部写入stdout,再触发底层流的刷新,配合setbuf(stdout, NULL)可以彻底关掉两层缓冲,代码示例:#include <fmt/color.h> #include <cstdio> int main() { setbuf(stdout, NULL); // 关闭C标准库层的stdout缓冲 fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Hello, {}!\n", "world"); fmt::flush(stdout); // 主动刷新fmt层缓冲 fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | fmt::emphasis::underline, "Hello, {}!\n", "???"); fmt::flush(stdout); fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "Hello, {}!\n", "??"); fmt::flush(stdout); } - 方案2:开启fmt输出流的自动刷新
如果不想每次手动加flush,可以用fmt提供的输出流包装,开启自动刷新属性,后续所有print操作都会自动触发缓冲刷新:#include <fmt/color.h> #include <cstdio> int main() { setbuf(stdout, NULL); auto out = fmt::output_file(stdout); out.set_autoflush(true); // 开启自动刷新 out.print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Hello, {}!\n", "world"); // 后续所有out.print调用都不需要手动flush out.print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | fmt::emphasis::underline, "Hello, {}!\n", "???"); out.print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "Hello, {}!\n", "??"); } - 方案3:调整IDE输出面板配置
如果你用的是Qt Creator这类IDE,哪怕代码侧的缓冲全部关闭,部分版本的IDE默认会按固定块大小读取管道内容,不会逐字符实时显示。需要在IDE设置里找到「应用输出」相关配置项,打开「强制立即刷新标准输出」的开关,配合代码侧的缓冲设置才能实现单步时的实时输出。
内容的提问来源于stack exchange,提问作者KcFnMi
相关产品推荐
相关产品推荐

