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

使用GCC --wrap标志拦截assert()函数时链接失败问题排查

问题原因及解决方法

核心原因:assert是预处理宏,不是函数

你遇到的问题根源在于assert不是真正的函数,它是<assert.h>中定义的预处理宏。GCC的--wrap选项是在链接阶段对函数符号进行替换,但assert(0)在编译预处理阶段就会被展开成底层的断言实现函数(比如GCC下是__assert_fail),根本不会生成assert这个函数符号。

你代码中声明的__real_assert找不到对应的函数符号,所以链接时抛出undefined reference to 'assert'错误。而malloc这类函数是真正的库函数,没有被宏替换,所以--wrap能正常生效。

解决方法:拦截assert展开后的底层函数

要拦截断言调用,你需要针对assert展开后的实际函数进行wrap操作:

  1. 查看assert的展开内容:执行gcc -E fut.c可以看到预处理后的代码,assert(0)会被展开为类似:

    ((void) ((0) ? ((void)0) : __assert_fail ("0", "fut.c", 6, __func__)))
    

    这里实际调用的是__assert_fail函数。

  2. 修改代码拦截__assert_fail:
    更新main.c中的wrap函数,替换为针对__assert_fail的实现:

    #include "fut.h"
    #include <stdio.h>
    
    static int useRealAssert = 1;
    static int assertCalled;
    
    // 声明真实的__assert_fail函数
    void __real___assert_fail(const char *assertion, const char *file, unsigned int line, const char *function);
    
    // wrap __assert_fail函数
    void __wrap___assert_fail(const char *assertion, const char *file, unsigned int line, const char *function)
    {
        if (useRealAssert)
        {
            __real___assert_fail(assertion, file, line, function);
        }
        else
        {
            assertCalled = 1;
        }
    }
    
    int main()
    {
        useRealAssert = 0;
    
        printf("Calling fut...\n");
        fut(1);
        printf("assertCalled = %d\n", assertCalled);
        return 0;
    }
    
  3. 更新编译命令:
    将--wrap的目标改为__assert_fail:

    gcc.exe -Wl,--wrap=__assert_fail -o my_program main.c fut.c
    

执行后就能成功拦截fut函数中的断言调用,输出assertCalled = 1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:52:46