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

Linux下如何用共享库重定向C库函数且保留原函数访问?

解决Linux下GCC --wrap机制不触发包装函数的问题

问题背景

我开发了一款堆内存跟踪包装库,封装了calloc()、malloc()等内存分配函数,在macOS环境下运行正常。移植到Ubuntu 22.04(GCC11.4)、Debian12(GCC12.2)(目标C11标准)后,采用--wrap=symbol及__wrap_*/__real_*机制编译运行无报错,但包装函数从未被触发——库已确认加载,内存操作计数始终为0。此问题与静态链接类同类问题无关,需实现包装逻辑同时调用原函数。

排查与解决方法

  • 修正编译链接顺序
    GCC的--wrap选项生效严格依赖链接顺序,必须将你的包装库放在被跟踪的目标程序/依赖库之后链接。示例编译命令:

    gcc -std=c11 your_program.c -o your_program -Wl,--wrap=malloc,--wrap=calloc -lyour_wrapper_lib
    

    若包装库前置,链接器会优先绑定系统库的原函数,直接跳过wrap机制。

  • 强制动态库加载优先级
    若包装库为动态库,Linux动态链接器可能优先加载系统库的原函数,可通过LD_PRELOAD强制优先加载你的包装库:

    LD_PRELOAD=./libyour_wrapper_lib.so ./your_program
    
  • 绕过链接器限制获取原函数
    部分程序或第三方库会通过dlsym直接获取内存分配函数地址,绕过--wrap机制。此时可在包装库中直接通过dlsym(RTLD_NEXT)获取原函数地址,替代__real_*:

    #include <dlfcn.h>
    
    void* __wrap_malloc(size_t size) {
        static void* (*real_malloc)(size_t) = NULL;
        if (!real_malloc) {
            real_malloc = dlsym(RTLD_NEXT, "malloc");
        }
        // 你的内存跟踪逻辑
        void* ptr = real_malloc(size);
        // 更新内存计数等操作
        return ptr;
    }
    

    编译时需链接动态加载库:-ldl

  • 验证wrap符号导出状态
    使用nm命令检查包装库是否正确导出__wrap_*系列符号:

    nm -D libyour_wrapper_lib.so | grep __wrap_
    

    若未找到对应符号,检查编译选项:动态库需加-fPIC,避免使用-fvisibility=hidden隐藏符号。

  • C++程序适配处理
    若目标程序为C++编写,malloc可能被operator new间接调用,需同时包装operator new;且包装函数需用extern "C"避免名字修饰:

    extern "C" {
    void* __wrap_malloc(size_t size) {
        // 跟踪逻辑
    }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:52:48