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

为何自定义malloc无法拦截库函数strdup的malloc调用?

问题:strdup调用malloc未触发__wrap_malloc日志的原因?

我通过GCC的-Wl,--wrap=malloc/-Wl,--wrap=free选项包装了malloc和free函数,实现了带日志打印的__wrap_malloc与__wrap_free。根据手册说明,strdup会调用malloc,但运行代码时,直接调用malloc能触发自定义日志,而strdup调用的malloc却未触发,仅能看到一次自定义malloc日志,却能看到两次自定义free日志。环境为x86架构Ubuntu虚拟机。

代码(main.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void* __real_malloc(size_t size);
void __real_free(void* ptr);

void* __wrap_malloc(size_t size)
{
    void *ptr = __real_malloc(size);
    printf("custom malloc size=%ld ptr=%p\n", size, ptr);
    return ptr;
}

void __wrap_free(void* ptr)
{
    printf("custom free ptr=%p\n", ptr);
    __real_free(ptr);
}

// gcc -o mybin main.c -Wl,--wrap=malloc -Wl,--wrap=free
int main() {

    const char *original = "Hello, World!";
    char *copy;

    copy = strdup(original);
    printf("Original: %s\n", original);
    printf("Copy: %s\n", copy);

    void *ptr = malloc(100);

    free(ptr);
    free(copy);

    return 0;
}

运行输出

Original: Hello, World!
Copy: Hello, World!
custom malloc size=100 ptr=0x55a845ef06d0
custom free ptr=0x55a845ef06d0
custom free ptr=0x55a845ef02a0

原因分析

核心原因是strdup属于libc内部函数,它在库内部直接调用的是私有版本的__libc_malloc,而非公开的malloc符号,而GCC的--wrap选项仅对代码中直接引用公开符号的调用生效:

  1. --wrap=symbol的工作原理是让链接器把编译单元中所有对symbol的引用替换为__wrap_symbol,同时将__real_symbol指向原符号。但这个替换只作用于你自己编写的代码,无法修改预编译好的libc内部函数的调用逻辑。
  2. 系统strdup是预编译的库函数,它内部直接调用libc私有malloc实现,不会触发对公开malloc符号的引用,因此你的__wrap_malloc不会被触发。
  3. 而free的情况不同:当你在代码中调用free(copy)时,是直接引用公开的free符号,链接器会将其替换为__wrap_free,不管指针来自哪里,都会走你的包装函数,因此能看到两次free日志。

解决办法

  • 若要拦截所有malloc调用(包括libc内部的),可以使用LD_PRELOAD加载自定义动态库,覆盖libc中的malloc符号。
  • 手动实现自己的strdup函数,在其中调用你包装后的malloc,替代系统的strdup。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:35:59