内存泄漏定制能力开放使用指导
==============

#### 概述

三方应用的内存泄漏问题往往难以定位，传统分析方式效率低下。为提升排查效率，HarmonyOS提供了MallocDispatchTable机制，支持开发者定制内存分配函数的Hook行为，灵活插入自定义监控逻辑，从而实现对内存分配行为的精准追踪与泄漏场景的主动捕获。通过这一能力，开发者可按需定制Hook策略，如记录调用栈、统计分配频次、设置阈值告警等，显著增强内存泄漏问题的定制化分析能力。

注：Hook是计算机编程中的一种钩子技术，它允许开发者拦截、修改或扩展函数的行为。通过使用钩子，开发者可以注入自定义代码，在特定事件发生时修改程序的行为。

本文将介绍以下内容：

*   [MallocDispatchTable简介](#section192072233251)
*   [MallocDispatchTable的Hook流程](#section18679163332511)
*   [场景案例](#section1893852252419)

#### 实现原理

#### \[h2\]MallocDispatchTable简介

MallocDispatchTable简称内存分配表，提供对HarmonyOS [libc标准库](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/musl)中的malloc、calloc、realloc、free等内存操作系列函数的Hook能力。此能力可用于跟踪应用的内存分配/释放信息，辅助内存泄漏问题快速定界定位。

注：内存基础知识参考文档：[内存基础知识](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-memory-basic-knowledge#section085818715389)。

#### \[h2\]MallocDispatchTable的Hook流程

如下图示例，开发者可使用自定义函数替换标准库函数，应用程序调用标准库函数时实际上执行的是自定义的函数。通过MallocDispatchTable里的函数指针，调用标准库函数时可以重定向到自定义的函数。MallocDispatchTable的主要功能在于将标准库函数的实现和自定义函数进行解耦。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/54/v3/LViss76nQPuJUnHFniWrtw/zh-cn_image_0000002501437914.png?HW-CC-KV=V1&HW-CC-Date=20260612T074627Z&HW-CC-Expire=86400&HW-CC-Sign=D31A73ED29EF94C98C096B6C1FFABD1E4807F88D08596CA45694EB9A9CB3271C)

开发人员可使用提供的[OH\_HiDebug\_SetMallocDispatchTable()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-hidebug-h#oh_hidebug_setmallocdispatchtable)接口设置libc标准库中使用的MallocDispatchTable；使用[OH\_HiDebug\_GetDefaultMallocDispatchTable()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-hidebug-h#oh_hidebug_getdefaultmallocdispatchtable)接口获取libc中默认的MallocDispatchTable。

#### 场景案例

#### \[h2\]场景描述

开发者观察到程序的匿名内存大小持续上涨，需要记录程序调用标准库的mmap和munmap函数的信息（包括分配内存大小、地址），从而统计使用mmap分配但未被释放（未记录到使用munmap释放对应内存地址）的内存大小。

#### \[h2\]开发步骤

1.  **添加头文件依赖。**
    
    #include "hidebug/hidebug.h"
    #include "hidebug/hidebug\_type.h"
    
    开发首先需要引用MallocDispatchTable相关的头文件。
    
2.  **创建自定义mmap和munmap方法。**
    
    static void\* MyMmap(void\* addr, size\_t len, int prot, int flags, int fd, off\_t offset)
    {
        HiDebug\_MallocDispatch\* original = (HiDebug\_MallocDispatch\*)OH\_HiDebug\_GetDefaultMallocDispatchTable();
        void\* returnAddr = original->mmap(addr, len, prot, flags, fd, offset);
        OH\_LOG\_INFO(LOG\_APP, "test MyMmap with len:%{public}d and addr:%{public}p", len, returnAddr);
        return returnAddr;
    }
    
    static int MyMunmap(void\* addr, size\_t len)
    {
        HiDebug\_MallocDispatch\* original = (HiDebug\_MallocDispatch\*)OH\_HiDebug\_GetDefaultMallocDispatchTable();
        OH\_LOG\_INFO(LOG\_APP, "test MyMunmap with len:%{public}d and addr:%{public}p", len, addr);
        return original->munmap(addr, len);
    }
    
    自定义的函数中将内存地址（函数参数addr）以及内存区间大小（函数参数len）通过日志打印。
    
3.  **创建一个[HiDebug\_MallocDispatch](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-hidebug-hidebug-mallocdispatch)类型的分配表。**
    
    //Obtain default MallocDispatchTable that can allocate memory directly.
    HiDebug\_MallocDispatch\* original = (HiDebug\_MallocDispatch\*)OH\_HiDebug\_GetDefaultMallocDispatchTable();
    //Create a MallocDispatchTable struct called current.
    HiDebug\_MallocDispatch\* current = (HiDebug\_MallocDispatch\*)original->malloc(sizeof(HiDebug\_MallocDispatch));
    memset(current, 0, sizeof(HiDebug\_MallocDispatch));
    //replace function pointers of current, from which self-defined functions can be redirected.
    current->mmap = MyMmap;
    current->munmap = MyMunmap;
    
    创建一个HiDebug\_MallocDispatch结构体current，通过[OH\_HiDebug\_GetDefaultMallocDispatchTable()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-hidebug-h#oh_hidebug_getdefaultmallocdispatchtable)分配其占用的堆内存。修改结构体中的函数指针，让其指向之前定义的MyMmap和MyMunmap函数。
    
4.  **启用自定义 MallocDispatchTable。**
    
    OH\_HiDebug\_SetMallocDispatchTable(current);
    
    将[libc标准库](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/musl)中使用的MallocDispatchTable替换成自定义的分配表。
    
5.  **调用libc标准库中的mmap函数。**
    
    char\* mapPtr = nullptr;
    const size\_t bufferSize = 100;  // 100 : the size of memory
    mapPtr = (char\*)mmap(nullptr, bufferSize, PROT\_READ | PROT\_WRITE, MAP\_SHARED | MAP\_ANONYMOUS, -1, 0);
    if (mapPtr == MAP\_FAILED) {
        printf("mmap failed\\n");
        return;
    }
    munmap(mapPtr, bufferSize);
    
    在执行上述基础库mmap函数时，会自动重定向到先前定义的MyMmap函数，完成业务自定义功能。
    
6.  **停用自定义 MallocDispatchTable。**
    
    //release memory of self-defined MallocDispatchTable struct.
    HiDebug\_MallocDispatch\* original = (HiDebug\_MallocDispatch\*)OH\_HiDebug\_GetDefaultMallocDispatchTable();
    original->free(current);
    //reset MallocDispatchTable strut that libc uses.
    OH\_HiDebug\_RestoreMallocDispatchTable();
    
    调用[OH\_HiDebug\_RestoreMallocDispatchTable()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-hidebug-h#oh_hidebug_restoremallocdispatchtable)接口可以恢复标准库默认的MallocDispatchTable。
    
7.  **CMakeLists.txt文件中添加如下依赖项。**
    
    add\_library(entry SHARED napi\_init.cpp test\_backtrace.cpp test\_malloc\_dispatch.cpp)
    target\_link\_libraries(entry PUBLIC libace\_napi.z.so libhilog\_ndk.z.so libohhidebug.so)
    

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e3/v3/7Y8GdD1GQlGYMnbJiYSVNA/caution_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T074627Z&HW-CC-Expire=86400&HW-CC-Sign=965D9146D57D1399D36966150BBFEB2E40D8E54E5C9C4258F68F7B549D68053E)

若应用程序设置了自定义的MallocDispatchTable，则与HarmonyOS提供的部分机制存在互斥，请在上述步骤4启用自定义MallocDispatchTable后注意。

具体限制如下：

1.  无法通过GWP-ASan功能进行内存越界检测。GWP-ASan 的工作原理详见文档：[GWP-ASan检测原理](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-stability-address-sanitizer-principle#section555616291854)。
2.  无法通过使用[native hook插件](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/hiprofiler#native-hook插件)对该应用程序进行函数调用栈捕获。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/42/v3/CW2nL-6LQgWQWB1xi7gHmw/warning_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T074627Z&HW-CC-Expire=86400&HW-CC-Sign=65BADDB94E34105D8E0298B32118A3FD23A7EEA3CDAF126C83AAF11EFB311670)

1.  禁止在自定义方法中调用[libc标准库](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/musl)内存操作函数（malloc/free/mmap/munmap），否则会导致死循环。
2.  禁止在自定义malloc方法中使用[hilog](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/hilog)进行日志打印，否则会导致死锁问题。

#### 示例代码

*   [性能分析工具](https://gitcode.com/HarmonyOS_Samples/guide-snippets/blob/master/PerformanceAnalysisKit/HiDebugTool/README_zh.md)