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

自定义fprintf()未触发调用求助:fopen/fclose可正常拦截

解决你的fprintf拦截失效问题

嘿,我看了你的代码和问题描述,很快就发现了几个导致fprintf worked!没出现的原因,咱们一步步解决:

核心问题1:fprintf被编译器优化绕开,且拦截逻辑有疏漏

首先,你的测试程序里fprintf(fr, "%s", "Papa Don't Preach")这种格式固定、参数为字符串常量的调用,会被GCC自动优化成fwrite(因为fwrite不需要解析格式字符串,效率更高),直接跳过了你的fprintf拦截函数。另外,你自定义的fprintf直接调用了vfprintf,但没有绑定标准库的真实vfprintf实现,逻辑上也存在隐患。

核心问题2:指针转整数的潜在错误

你代码里直接把FILE*强转成int(比如sprintf(fidString, "fopen %d ", fp);),在64位系统上会丢失指针的高位字节,导致输出错误的标识,得用intptr_t来安全转换。


修复步骤来啦:

1. 修改共享库的fprintf拦截逻辑

咱们直接绑定标准库的vfprintf(因为标准库的fprintf本质就是基于vfprintf实现的),确保拦截逻辑能覆盖所有场景:

首先在共享库的全局变量区添加real_vfprintf指针,并引入必要头文件:

#include <stdint.h> // 用于安全转换指针为整数

static int (*real_vfprintf)(FILE *stream, const char *format, va_list arg) = NULL;

然后在初始化函数my_lib_init里初始化这个指针:

__attribute__((constructor)) void my_lib_init(void) {
    // ... 其他原有初始化代码保持不变
    real_vfprintf = dlsym(RTLD_NEXT, "vfprintf");
}

最后修改你的fprintf拦截函数:

int fprintf(FILE *stream, const char *format, ...) {
    va_list arg;
    int done;

    // 双重检查,确保真实函数指针有效
    if (!real_vfprintf) {
        real_vfprintf = dlsym(RTLD_NEXT, "vfprintf");
    }

    va_start(arg, format);
    done = real_vfprintf(stream, format, arg); // 调用标准库的真实实现
    va_end(arg);

    printf("fprintf worked!\n");
    char message[200];
    // 用intptr_t安全转换FILE*为整数,避免64位系统出错
    sprintf(message, "fprintf %" PRIdPTR "", (intptr_t)stream);
    sendMessage(message);
    return done;
}

2. 编译测试程序时禁用fprintf优化

编译测试程序时加上-fno-builtin-fprintf参数,禁止GCC把fprintf替换成fwrite:

LD_PRELOAD=./file_io_operation_interception.so gcc -fno-builtin-fprintf -o file_operations_test file_operations_test.c

3. 修复其他指针转整数的地方

把fopen和fclose里的指针转换也改成安全的方式:

// fopen函数里的代码修改:
char fidString[30]; // 扩大缓冲区避免溢出
sprintf(fidString, "fopen %" PRIdPTR " ", (intptr_t)fp);

// fclose函数里的代码修改:
sprintf(message, "fclose %" PRIdPTR "", (intptr_t)fp);

重新编译运行

按照以下步骤重新操作:

  1. 重新编译共享库:
gcc -fpic -c file_io_operation_interception.c
gcc -shared -lc -ldl -o file_io_operation_interception.so file_io_operation_interception.o

(注:编译.c文件时不需要-ldl,链接共享库时添加即可)

  1. 编译测试程序(带禁用优化参数):
LD_PRELOAD=./file_io_operation_interception.so gcc -fno-builtin-fprintf -o file_operations_test file_operations_test.c
  1. 运行测试程序:
LD_PRELOAD=./file_io_operation_interception.so ./file_operations_test

这下你就能在输出里看到fprintf worked!啦!


额外小提示

以后遇到可变参数函数的拦截问题,优先拦截对应的v版函数(比如vfprintf、vprintf),因为标准库中很多可变参数函数都是基于v版实现的,这样能避免被编译器优化绕开,覆盖更多场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:19:02