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

使用Sanitizer编译时,fflush传入无效FILE指针返回0的问题咨询

问题:fflush传入已关闭文件指针时 sanitizer 编译下返回值异常

根据fflush的文档说明,该函数成功时返回0,失败时返回EOF(本机EOF值为-1)。编写的测试代码如下:

#include<cstdio>
#include<iostream>

int main()
{
    FILE* fp = std::fopen("/tmp/test", "w+");
    std::fclose(fp);

    std::cout << std::fflush(fp) << std::endl;
    return 0;
}

现象:使用g常规编译或带-O2 -DNDEBUG参数编译时,程序输出-1,符合预期;但使用-fsanitize=address或-fsanitize=thread参数编译时(clang编译也会出现相同情况),程序输出0。测试环境为Debian 12 amd64,使用g-12、clang-15,结果一致。


解答

首先要明确:调用fflush传入已关闭的FILE*属于未定义行为,C语言标准没有规定这种场景下的返回值,不同的标准库实现(包括启用sanitizer后的库行为)可以自由处理这个情况,返回任何值都是允许的。

具体原因拆解:

  • 常规编译时,glibc(或系统默认libc)的fflush实现会检测FILE指针的内部状态(比如已关闭的标志),判断出指针失效,因此返回EOF(-1)。
  • 启用AddressSanitizer/ThreadSanitizer时,sanitizer会替换或包装标准库的FILE结构及相关函数。此时fflush的包装逻辑优先级是检测内存安全问题,而非遵循未定义场景的常规返回值:
    • 可能sanitizer已经清理了已关闭FILE对象的相关内存结构,导致原本的错误检测逻辑无法触发;
    • 也可能sanitizer的包装函数直接返回0,因为它的核心目标是在运行时抛出内存错误警告(你可以查看程序的标准错误输出,应该能看到类似“使用已释放的FILE对象”的提示),而非保证未定义行为下的返回值符合预期。

简单来说,这种返回值差异是未定义行为的正常表现,sanitizer的存在改变了标准库函数在非法输入下的处理逻辑,重点应该关注sanitizer抛出的内存错误警告,而非纠结未定义场景下的返回值。


内容的提问来源于stack exchange,提问作者byteunit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 17:53:24