使用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操作:
查看assert的展开内容:执行
gcc -E fut.c可以看到预处理后的代码,assert(0)会被展开为类似:((void) ((0) ? ((void)0) : __assert_fail ("0", "fut.c", 6, __func__)))这里实际调用的是
__assert_fail函数。修改代码拦截__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; }更新编译命令:
将--wrap的目标改为__assert_fail:gcc.exe -Wl,--wrap=__assert_fail -o my_program main.c fut.c
执行后就能成功拦截fut函数中的断言调用,输出assertCalled = 1。
内容的提问来源于stack exchange,提问作者adamm
相关产品推荐
相关产品推荐

