第一部分 架构

项目模块目录:

1. include/mm.h

/**
 * @file mm.h
 * @brief 内存管理模块 - 独立内存池管理系统
 * @author Memory Manager Team
 * @version 2.0.0
 * 
 * @section 设计原则 (内存管理七字诀)
 * ① 预分配,不动态     所有内存池在编译时或初始化时一次性分配
 * ② 定大小,不分片     每个池的槽位大小固定,避免内存碎片
 * ③ 池化管理,零碎片   使用槽位池管理,分配释放无碎片
 * ④ 谁申请,谁释放     明确所有权,申请者负责释放
 * ⑤ 引用计数,防泄漏   支持引用计数,自动管理共享内存
 * ⑥ 对齐边界,性能优   内存按64字节对齐,缓存友好
 * ⑦ 栈优先,堆次之     小对象用栈,大对象用池
 * ⑧ 静态区,放常量     配置信息放在只读数据段
 * 
 * @section 使用示例
 * @code
 * // 初始化
 * mm_init();
 * 
 * // 从张量池分配内存
 * void* data = mm_alloc(MM_POOL_TENSOR, 1024);
 * 
 * // 使用数据
 * memset(data, 0, 1024);
 * 
 * // 增加引用计数(共享)
 * mm_ref(data);
 * 
 * // 释放引用
 * mm_unref(MM_POOL_TENSOR, data);
 * 
 * // 查看统计
 * mm_dump(stdout);
 * 
 * // 清理
 * mm_deinit();
 * @endcode
 */
​
 #ifndef MM_H
 #define MM_H
 
 #include <stdint.h>
 #include <stddef.h>
 #include <stdbool.h>
 #include <stdio.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*============================================================================
  * 编译时配置
  *============================================================================*/
 
 /**
  * @defgroup 编译配置
  * @{
  */
 
 /** @brief 最大内存池数量(包括动态池) */
 #define MM_MAX_POOLS           16
 
 /** @brief 内存对齐字节数(口诀⑥:对齐边界,性能优) */
 #define MM_ALIGNMENT           64
 
 /** @brief 块头魔数,用于检测内存损坏 */
 #define MM_MAGIC               0x4D4D4D4D
 
 /** @brief 调试模式开关(1=启用追踪,0=禁用) */
 #ifndef MM_DEBUG
     #define MM_DEBUG 0
 #endif
 
 /** @} */
 
 /*============================================================================
  * 错误码定义
  *============================================================================*/
 
 /**
  * @defgroup 错误码
  * @{
  */
 
 /**
  * @brief 内存管理模块错误码
  */
 typedef enum {
     MM_OK = 0,                      /**< 操作成功 */
     MM_ERR_INVALID_POOL = -1,       /**< 无效的内存池ID */
     MM_ERR_OUT_OF_MEMORY = -2,      /**< 内存不足 */
     MM_ERR_INVALID_PTR = -3,        /**< 无效的内存指针 */
     MM_ERR_SIZE_TOO_LARGE = -4,     /**< 请求大小超过槽位限制 */
     MM_ERR_POOL_FULL = -5,          /**< 内存池已满 */
     MM_ERR_NOT_INITIALIZED = -6,    /**< 模块未初始化 */
     MM_ERR_CORRUPTED = -7,          /**< 内存块损坏(魔数校验失败) */
 } mm_error_t;
 
 /**
  * @brief 获取错误码对应的描述字符串
  * @param err 错误码
  * @return 错误描述字符串
  */
 const char* mm_error_string(mm_error_t err);
 
 /** @} */
 
 /*============================================================================
  * 内存池类型
  *============================================================================*/
 
 /**
  * @defgroup 预定义池类型
  * @{
  */
 
 /**
  * @brief 预定义内存池类型
  * 
  * 这些池在 mm_init() 时自动创建,使用静态内存。
  */
 typedef enum {
     MM_POOL_TENSOR = 0,     /**< 张量数据池 - 512KB, 8槽位, 每槽64KB */
     MM_POOL_MODEL  = 1,     /**< 模型数据池 - 1MB, 4槽位, 每槽256KB */
     MM_POOL_FRAME  = 2,     /**< 帧缓冲池 - 256KB, 4槽位, 每槽64KB */
     MM_POOL_CUSTOM = 3,     /**< 自定义池起始索引 */
 } mm_pool_type_t;
 
 /** @} */
 
 /*============================================================================
  * 数据结构定义
  *============================================================================*/
 
 /**
  * @defgroup 数据结构
  * @{
  */
 
 /**
  * @brief 内存块头部结构
  * 
  * 每个分配的内存块前都有一个头部,用于管理。
  * 布局: [mm_block_t][user_data...]
  *       ^             ^
  *       block         user_ptr
  */
/* 修改 mm_block_t 结构体定义,添加64字节对齐属性 */
typedef struct mm_block {
    struct mm_block* next;      /**< 下一个空闲块 */
    uint32_t ref_count;         /**< 引用计数 */
    uint32_t magic;             /**< 魔数校验 */
    size_t size;                /**< 用户数据大小 */
    int pool_id;                /**< 所属池ID */
    uint32_t slot_idx;          /**< 槽位索引 */
    uint32_t alloc_line;        /**< 分配行号 */
    const char* alloc_file;     /**< 分配文件名 */
    void* user_ptr;             /**< 用户数据指针 */
} __attribute__((aligned(64))) mm_block_t;
 
 /**
  * @brief 内存池配置信息
  * 
  * 描述一个内存池的基本属性,存储在只读数据段(口诀⑧:静态区,放常量)。
  */
 typedef struct {
     const char* name;           /**< 池名称 */
     size_t total_size;          /**< 总大小(字节) */
     size_t slot_size;           /**< 单槽大小(字节,包含头部) */
     size_t slot_count;          /**< 槽位数量 */
     size_t alignment;           /**< 对齐边界(字节) */
     int is_dynamic;             /**< 是否动态池(0=静态,1=动态) */
 } mm_pool_config_t;
 
 /**
  * @brief 内存池统计信息
  * 
  * 用于查询内存池的使用情况。
  */
 typedef struct {
     const char* name;           /**< 池名称 */
     size_t slot_size;           /**< 槽位大小(字节) */
     size_t total_slots;         /**< 总槽位数 */
     size_t used_slots;          /**< 已使用槽位数 */
     size_t free_slots;          /**< 空闲槽位数 */
     size_t total_alloc_bytes;   /**< 当前分配总字节数 */
     size_t peak_alloc_bytes;    /**< 历史峰值分配字节数 */
     uint64_t alloc_count;       /**< 历史分配次数 */
     uint64_t free_count;        /**< 历史释放次数 */
     uint64_t leak_count;        /**< 泄漏次数(仅检测时有效) */
 } mm_stats_t;
 
 /** @} */
 
 /*============================================================================
  * 核心API - 初始化和销毁
  *============================================================================*/
 
 /**
  * @defgroup 初始化和销毁
  * @{
  */
 
 /**
  * @brief 初始化内存管理模块
  * 
  * 创建所有预定义的内存池,初始化空闲链表。
  * 遵循口诀①:预分配,不动态
  * 
  * @return 错误码
  * @retval MM_OK 初始化成功
  * @retval MM_ERR_OUT_OF_MEMORY 内存不足
  * 
  * @note 必须在任何其他内存操作之前调用
  */
 mm_error_t mm_init(void);
 
 /**
  * @brief 反初始化内存管理模块
  * 
  * 释放所有动态内存池,检测并报告内存泄漏。
  * 
  * @return 错误码
  * @retval MM_OK 反初始化成功
  * 
  * @note 调用后所有之前分配的内存指针将失效
  */
 mm_error_t mm_deinit(void);
 
 /**
  * @brief 检查模块是否已初始化
  * @return true=已初始化, false=未初始化
  */
 bool mm_is_initialized(void);
 
 /** @} */
 
 /*============================================================================
  * 内存池管理API
  *============================================================================*/
 
 /**
  * @defgroup 内存池管理
  * @{
  */
 
 /**
  * @brief 创建自定义内存池(动态池)
  * 
  * @param name 池名称(不能重复)
  * @param slot_size 槽位大小(字节)
  * @param slot_count 槽位数量
  * @param out_pool_id 输出池ID
  * @return 错误码
  * @retval MM_OK 创建成功
  * @retval MM_ERR_INVALID_PTR 参数无效
  * @retval MM_ERR_OUT_OF_MEMORY 内存不足
  * 
  * @note 动态池使用 malloc 分配内存,但内部管理仍是固定槽位
  */
 mm_error_t mm_pool_create(const char* name, size_t slot_size, size_t slot_count, int* out_pool_id);
 
 /**
  * @brief 销毁自定义内存池
  * @param pool_id 池ID
  * @return 错误码
  * @retval MM_OK 销毁成功
  * @retval MM_ERR_POOL_FULL 池中仍有未释放的内存
  * 
  * @note 只能销毁动态池,不能销毁预定义池
  */
 mm_error_t mm_pool_destroy(int pool_id);
 
 /**
  * @brief 获取预定义池的ID
  * @param type 池类型
  * @return 池ID,失败返回-1
  */
 int mm_pool_id(mm_pool_type_t type);
 
 /**
  * @brief 获取池配置信息
  * @param pool_id 池ID
  * @param config 输出配置
  * @return 错误码
  */
 mm_error_t mm_pool_config(int pool_id, mm_pool_config_t* config);
 
 /** @} */
 
 /*============================================================================
  * 内存分配/释放API
  *============================================================================*/
 
 /**
  * @defgroup 分配释放
  * @{
  */
 
 /**
  * @brief 从指定池分配内存
  * 
  * 遵循口诀④:谁申请,谁释放
  * 
  * @param pool_id 池ID
  * @param size 需要的大小(字节,必须 ≤ 槽位大小)
  * @return 内存指针,失败返回NULL
  * 
  * @note 分配的内存自动清零
  * @note 分配后 ref_count = 1
  */
 void* mm_alloc(int pool_id, size_t size);
 
 /**
  * @brief 带调试信息的分配(通过宏调用)
  * 
  * @param pool_id 池ID
  * @param size 大小
  * @param file 文件名(由宏自动填充)
  * @param line 行号(由宏自动填充)
  * @return 内存指针
  */
 void* mm_alloc_dbg(int pool_id, size_t size, const char* file, int line);
 
 /**
  * @brief 释放内存
  * 
  * 遵循口诀④:谁申请,谁释放
  * 
  * @param pool_id 池ID
  * @param ptr 内存指针
  */
 void mm_free(int pool_id, void* ptr);
 
 /**
  * @brief 获取分配的内存块大小
  * @param ptr 内存指针
  * @return 实际分配大小(字节),失败返回0
  */
 size_t mm_get_size(void* ptr);
 
 /**
  * @brief 获取内存块所属池ID
  * @param ptr 内存指针
  * @return 池ID,失败返回-1
  */
 int mm_get_pool_id(void* ptr);
 
 /** @} */
 
 /*============================================================================
  * 引用计数API
  *============================================================================*/
 
 /**
  * @defgroup 引用计数
  * @{
  */
 
 /**
  * @brief 增加内存块的引用计数
  * 
  * 遵循口诀⑤:引用计数,防泄漏
  * 
  * @param ptr 内存指针
  * @return 新的引用计数,失败返回-1
  */
 int mm_ref(void* ptr);
 
 /**
  * @brief 减少内存块的引用计数
  * 
  * 当引用计数降为0时,自动释放内存。
  * 遵循口诀⑤:引用计数,防泄漏
  * 
  * @param pool_id 池ID
  * @param ptr 内存指针
  * @return 新的引用计数,失败返回-1
  */
 int mm_unref(int pool_id, void* ptr);
 
 /**
  * @brief 获取内存块的引用计数
  * @param ptr 内存指针
  * @return 引用计数,失败返回-1
  */
 int mm_refcount(void* ptr);
 
 /** @} */
 
 /*============================================================================
  * 统计和调试API
  *============================================================================*/
 
 /**
  * @defgroup 统计调试
  * @{
  */
 
 /**
  * @brief 获取内存池统计信息
  * @param pool_id 池ID
  * @param stats 输出统计信息
  * @return 错误码
  */
 mm_error_t mm_stats(int pool_id, mm_stats_t* stats);
 
 /**
  * @brief 打印所有内存池状态
  * @param out 输出流(NULL=stdout)
  */
 void mm_dump(FILE* out);
 
 /**
  * @brief 检测并报告内存泄漏
  * @param out 输出流(NULL=stdout)
  * @return 泄漏的块数量
  */
 int mm_check_leaks(FILE* out);
 
 /**
  * @brief 打印指定内存块的详细信息
  * @param ptr 内存指针
  * @param out 输出流(NULL=stdout)
  */
 void mm_dump_block(void* ptr, FILE* out);
​
 /**
 * @brief 重置指定内存池(清空所有分配)
 * @param pool_id 池ID
 * @return 错误码
 * @note 仅用于测试,强制释放所有内存
 */
mm_error_t mm_pool_reset(int pool_id);
​
/**
 * @brief 重置所有内存池
 * @note 仅用于测试
 */
void mm_reset_all(void);
 
 /** @} */
 
 /*============================================================================
  * 栈内存辅助宏
  *============================================================================*/
 
 /**
  * @defgroup 栈内存宏
  * @{
  */
 
 /**
  * @brief 在栈上分配数组(推荐用于 < 4KB 的数据)
  * 
  * 遵循口诀⑦:栈优先,堆次之
  * 
  * @param type 数组元素类型
  * @param name 数组变量名
  * @param size 数组大小
  */
 #define MM_STACK_ARRAY(type, name, size) \
     type name[size]; \
     memset(name, 0, sizeof(name))
 
 /**
  * @brief 在栈上分配并初始化数组
  * 
  * 遵循口诀⑦:栈优先,堆次之
  * 
  * @param type 数组元素类型
  * @param name 数组变量名
  * @param size 数组大小
  * @param init_val 初始值
  */
 #define MM_STACK_INIT(type, name, size, init_val) \
     type name[size]; \
     for (size_t _i = 0; _i < (size); _i++) name[_i] = (init_val)
 
 /** @} */
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* MM_H */
​

2. src/mm.c

/**
 * @file mm.c
 * @brief 内存管理模块实现
 * @author Memory Manager Team
 * @version 2.0.0
 * 
 * @details 实现内存池管理,严格遵循内存管理七字诀:
 *          ① 预分配,不动态    ② 定大小,不分片
 *          ③ 池化管理,零碎片  ④ 谁申请,谁释放
 *          ⑤ 引用计数,防泄漏  ⑥ 对齐边界,性能优
 *          ⑦ 栈优先,堆次之    ⑧ 静态区,放常量
 */

#include "mm.h"

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

/*============================================================================
* 调试宏 (MM_DEBUG=1 时启用追踪)
*============================================================================*/

#ifndef MM_DEBUG
    #define MM_DEBUG 0
#endif

#if MM_DEBUG
    #define MM_TRACE(fmt, ...) \
        printf("[MM_TRACE] %s:%d: " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
    #define MM_ERROR(fmt, ...) \
        printf("[MM_ERROR] %s:%d: " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
#else
    #define MM_TRACE(fmt, ...)
    #define MM_ERROR(fmt, ...)
#endif

/*============================================================================
* 静态内存池数据区 (口诀①: 预分配,不动态;口诀⑥: 对齐边界,性能优)
*============================================================================*/

/**
 * @brief 张量池 - 512KB,64字节对齐
 * 
 * 用于存储张量数据,8个槽位,每槽64KB。
 * 遵循口诀①:预分配,不动态
 * 遵循口诀⑥:对齐边界,性能优
 */
static uint8_t g_tensor_pool[512 * 1024] __attribute__((aligned(MM_ALIGNMENT)));

/**
 * @brief 模型池 - 1MB,64字节对齐
 * 
 * 用于存储模型数据,4个槽位,每槽256KB。
 * 遵循口诀①:预分配,不动态
 */
static uint8_t g_model_pool[1024 * 1024] __attribute__((aligned(MM_ALIGNMENT)));

/**
 * @brief 帧缓冲池 - 256KB,64字节对齐
 * 
 * 用于存储帧缓冲区,4个槽位,每槽64KB。
 * 遵循口诀①:预分配,不动态
 */
static uint8_t g_frame_pool[256 * 1024] __attribute__((aligned(MM_ALIGNMENT)));

/*============================================================================
* 预定义池配置表 (口诀⑧: 静态区,放常量)
*============================================================================*/

/**
 * @brief 预定义内存池配置表
 * 
 * 这些配置在编译时确定,存储在只读数据段。
 * 遵循口诀⑧:静态区,放常量
 */
static const mm_pool_config_t g_default_configs[] = {
    [MM_POOL_TENSOR] = {
        .name = "TensorPool",
        .total_size = 512 * 1024,
        .slot_size = 64 * 1024,
        .slot_count = 8,
        .alignment = MM_ALIGNMENT,
        .is_dynamic = 0,
    },
    [MM_POOL_MODEL] = {
        .name = "ModelPool",
        .total_size = 1024 * 1024,
        .slot_size = 256 * 1024,
        .slot_count = 4,
        .alignment = MM_ALIGNMENT,
        .is_dynamic = 0,
    },
    [MM_POOL_FRAME] = {
        .name = "FramePool",
        .total_size = 256 * 1024,
        .slot_size = 64 * 1024,
        .slot_count = 4,
        .alignment = MM_ALIGNMENT,
        .is_dynamic = 0,
    },
};

/*============================================================================
* 动态池结构定义
*============================================================================*/

/**
 * @brief 动态内存池结构
 * 
 * 用于管理运行时创建的自定义内存池。
 */
typedef struct dynamic_pool {
    char name[64];                  /**< 池名称 */
    mm_pool_config_t config;        /**< 池配置 */
    uint8_t* base_ptr;              /**< 池基地址(malloc分配) */
    mm_block_t* free_list;          /**< 空闲块链表头 */
    uint32_t* slot_used;            /**< 槽位使用标志数组 */
    size_t used_count;              /**< 已使用槽位数 */
    size_t free_count;              /**< 空闲槽位数 */
    uint64_t alloc_count;           /**< 历史分配次数 */
    uint64_t free_count_total;      /**< 历史释放次数 */
    size_t peak_alloc_bytes;        /**< 峰值分配字节数 */
    pthread_mutex_t mutex;          /**< 池互斥锁 */
    int initialized;                /**< 初始化标志 */
} dynamic_pool_t;

/*============================================================================
* 全局状态结构
*============================================================================*/

/**
 * @brief 全局内存管理状态
 * 
 * 管理所有内存池和全局统计信息。
 */
static struct {
    int initialized;                            /**< 初始化标志 */
    pthread_mutex_t global_mutex;               /**< 全局互斥锁 */
    
    /* 静态池数据 */
    uint8_t* static_pools[MM_POOL_CUSTOM];      /**< 静态池基地址 */
    mm_block_t* static_free_lists[MM_POOL_CUSTOM]; /**< 静态池空闲链表 */
    uint32_t static_slot_used[MM_POOL_CUSTOM][32]; /**< 静态池槽位使用标志 */
    size_t static_used_count[MM_POOL_CUSTOM];   /**< 静态池已用槽位数 */
    size_t static_free_count[MM_POOL_CUSTOM];   /**< 静态池空闲槽位数 */
    int static_initialized[MM_POOL_CUSTOM];     /**< 静态池初始化标志 */
    
    /* 动态池数据 */
    dynamic_pool_t dynamic_pools[MM_MAX_POOLS - MM_POOL_CUSTOM]; /**< 动态池数组 */
    int dynamic_pool_count;                     /**< 动态池数量 */
    
    /* 全局统计 */
    uint64_t total_alloc_count;                 /**< 总分配次数 */
    uint64_t total_free_count;                  /**< 总释放次数 */
    size_t total_alloc_bytes;                   /**< 总分配字节数 */
    uint64_t total_leak_count;                  /**< 总泄漏块数 */
    
} g_mm = {
    .initialized = 0,
    .global_mutex = PTHREAD_MUTEX_INITIALIZER,
    .static_pools = {NULL, NULL, NULL},
    .static_initialized = {0, 0, 0},
    .dynamic_pool_count = 0,
    .total_alloc_count = 0,
    .total_free_count = 0,
    .total_alloc_bytes = 0,
    .total_leak_count = 0,
};

/*============================================================================
* 内部辅助函数
*============================================================================*/
/**
 * @brief 从用户指针获取块头部
 * @param ptr 用户数据指针
 * @return 块头部指针,失败返回NULL
 */
static mm_block_t* block_from_ptr(void* ptr) {
    if (!ptr) return NULL;
    /* 由于 mm_block_t 是64字节对齐,用户指针紧跟其后,偏移量固定 */
    return (mm_block_t*)((uint8_t*)ptr - sizeof(mm_block_t));
}

/**
 * @brief 动态池释放函数
 * @param pool 动态池指针
 * @param ptr 要释放的内存指针
 * 
 * @note 增加双重释放保护,检查槽位是否已被释放
 * @note 此函数在 mm_free 中被调用
 */
static void dynamic_pool_free(dynamic_pool_t* pool, void* ptr) {
    mm_block_t* block = block_from_ptr(ptr);
    
    if (!block || block->magic != MM_MAGIC) {
        MM_ERROR("Invalid block at %p", ptr);
        return;
    }
    
    /* 验证 slot_idx 有效 */
    if (block->slot_idx >= pool->config.slot_count) {
        MM_ERROR("Invalid slot_idx %u (max %zu)", block->slot_idx, pool->config.slot_count);
        return;
    }
    
    pthread_mutex_lock(&pool->mutex);
    
    /* 关键修复:检查是否已经被释放,防止双重释放 */
    if (pool->slot_used[block->slot_idx] == 0) {
        MM_TRACE("Double free detected on slot %u", block->slot_idx);
        pthread_mutex_unlock(&pool->mutex);
        return;
    }
    
    block->ref_count = 0;
    pool->slot_used[block->slot_idx] = 0;
    pool->used_count--;
    pool->free_count++;
    pool->free_count_total++;
    
    block->next = pool->free_list;
    pool->free_list = block;
    
    MM_TRACE("Freed slot %u, used_count=%zu", block->slot_idx, pool->used_count);
    
    pthread_mutex_unlock(&pool->mutex);
}

/**
 * @brief 验证块头部完整性
 * @param block 块头部指针
 * @return 1=有效, 0=无效
 */
static int block_valid(mm_block_t* block) {
    uintptr_t addr;
    
    if (!block) return 0;
    
    addr = (uintptr_t)block;
    
    /* 检查是否在静态池范围内 */
    for (int i = 0; i < MM_POOL_CUSTOM; i++) {
        if (g_mm.static_initialized[i] && g_mm.static_pools[i]) {
            uintptr_t base = (uintptr_t)g_mm.static_pools[i];
            uintptr_t end = base + g_default_configs[i].total_size;
            if (addr >= base && addr < end) {
                return (block->magic == MM_MAGIC);
            }
        }
    }
    
    /* 检查是否在动态池范围内 */
    for (int i = 0; i < g_mm.dynamic_pool_count; i++) {
        dynamic_pool_t* pool = &g_mm.dynamic_pools[i];
        if (pool->initialized && pool->base_ptr) {
            uintptr_t base = (uintptr_t)pool->base_ptr;
            uintptr_t end = base + pool->config.total_size;
            if (addr >= base && addr < end) {
                return (block->magic == MM_MAGIC);
            }
        }
    }
    
    return 0;
}

/**
 * @brief 检查指针是否属于指定静态池
 * @param pool_id 池ID
 * @param ptr 内存指针
 * @return 1=属于, 0=不属于
 */
/*static int ptr_in_static_pool(int pool_id, void* ptr) {
    uintptr_t addr, base, end;
    
    if (!ptr) return 0;
    if (pool_id < 0 || pool_id >= MM_POOL_CUSTOM) return 0;
    if (!g_mm.static_pools[pool_id]) return 0;
    
    addr = (uintptr_t)ptr;
    base = (uintptr_t)g_mm.static_pools[pool_id];
    end = base + g_default_configs[pool_id].total_size;
    
    return (addr >= base && addr < end);
}*/

/*============================================================================
* 静态池初始化函数
*============================================================================*/

/**
 * @brief 初始化静态内存池
 * 
 * 由于 mm_block_t 已强制64字节对齐,sizeof(mm_block_t) 是64的倍数,
 * 所以 user_ptr 自然对齐到64字节边界。
 * 
 * @param pool_id 池ID (0-2)
 * @param config 池配置
 * @param base_ptr 池基地址
 */
static void init_static_pool(int pool_id, const mm_pool_config_t* config, uint8_t* base_ptr) {
    size_t slot_size = config->slot_size;
    size_t slot_count = config->slot_count;
    mm_block_t* prev = NULL;
    
    MM_TRACE("Initializing pool %s: base=%p, size=%zu, slots=%zu, slot_size=%zu",
             config->name, base_ptr, config->total_size, slot_count, slot_size);
    
    g_mm.static_pools[pool_id] = base_ptr;
    g_mm.static_used_count[pool_id] = 0;
    g_mm.static_free_count[pool_id] = slot_count;
    g_mm.static_initialized[pool_id] = 1;
    
    memset(g_mm.static_slot_used[pool_id], 0, sizeof(g_mm.static_slot_used[pool_id]));
    
    for (size_t i = 0; i < slot_count; i++) {
        uint8_t* slot_start = base_ptr + i * slot_size;
        mm_block_t* block = (mm_block_t*)slot_start;
        
        /* 由于 mm_block_t 已64字节对齐,用户指针自然对齐 */
        block->next = NULL;
        block->ref_count = 0;
        block->magic = MM_MAGIC;
        block->size = slot_size - sizeof(mm_block_t);
        block->pool_id = pool_id;
        block->slot_idx = i;
        block->alloc_line = 0;
        block->alloc_file = NULL;
        block->user_ptr = (uint8_t*)slot_start + sizeof(mm_block_t);
        
        if (prev) {
            prev->next = block;
        } else {
            g_mm.static_free_lists[pool_id] = block;
        }
        prev = block;
        
        MM_TRACE("  Slot %zu: user_ptr=%p, size=%zu", i, block->user_ptr, block->size);
    }
    
    MM_TRACE("Pool %s initialized, free_list=%p", config->name, g_mm.static_free_lists[pool_id]);
}

/*============================================================================
* 静态池分配释放函数
*============================================================================*/

/**
 * @brief 从静态池分配内存
 * @param pool_id 池ID
 * @param size 需要的大小
 * @param file 分配文件名(调试用)
 * @param line 分配行号(调试用)
 * @return 内存指针,失败返回NULL
 */
static void* static_pool_alloc(int pool_id, size_t size, const char* file, int line) {
    mm_block_t* block;
    void* result;
    
    MM_TRACE("Alloc from pool %d: size=%zu, file=%s:%d", pool_id, size, file ? file : "?", line);
    
    if (!g_mm.static_initialized[pool_id]) {
        MM_ERROR("Pool %d not initialized!", pool_id);
        return NULL;
    }
    
    block = g_mm.static_free_lists[pool_id];
    if (!block) {
        MM_ERROR("No free block in pool %d", pool_id);
        return NULL;
    }
    
    /* 检查大小是否超过槽位容量 */
    if (size > block->size) {
        MM_ERROR("Size %zu > block capacity %zu", size, block->size);
        return NULL;  /* 关键修复:返回NULL,不分配 */
    }
    
    MM_TRACE("  Got block at %p, slot_idx=%u, user_ptr=%p, capacity=%zu", 
             block, block->slot_idx, block->user_ptr, block->size);
    
    /* 从链表中移除 */
    g_mm.static_free_lists[pool_id] = block->next;
    
    /* 标记槽位已使用 */
    g_mm.static_slot_used[pool_id][block->slot_idx] = 1;
    g_mm.static_used_count[pool_id]++;
    g_mm.static_free_count[pool_id]--;
    
    /* 保存请求的大小 */
    block->size = size;
    block->ref_count = 1;
    block->magic = MM_MAGIC;
    block->pool_id = pool_id;
    block->alloc_line = line;
    block->alloc_file = file;
    
    result = block->user_ptr;
    memset(result, 0, size);
    
    MM_TRACE("  Allocated %p, size=%zu", result, size);
    
    g_mm.total_alloc_count++;
    g_mm.total_alloc_bytes += size;
    
    return result;
}

/**
 * @brief 释放内存回静态池
 * @param pool_id 池ID
 * @param ptr 内存指针
 */
/*static void static_pool_free(int pool_id, void* ptr) {
    mm_block_t* block;
    size_t slot_size = g_default_configs[pool_id].slot_size;
    
    MM_TRACE("Free from pool %d: ptr=%p", pool_id, ptr);
    
    if (!ptr_in_static_pool(pool_id, ptr)) {
        MM_ERROR("Pointer %p not in pool %d", ptr, pool_id);
        return;
    }
    
    block = block_from_ptr(ptr);
    if (!block_valid(block)) {
        MM_ERROR("Invalid block at %p", ptr);
        return;
    }
    
    MM_TRACE("  Block at %p, slot_idx=%u, size=%zu, ref=%u", 
             block, block->slot_idx, block->size, block->ref_count);
    
    block->ref_count = 0;
    block->alloc_line = 0;
    block->alloc_file = NULL;
    
    // 关键修复:恢复块容量为槽位容量 
    block->size = slot_size - sizeof(mm_block_t);
    
    g_mm.static_slot_used[pool_id][block->slot_idx] = 0;
    g_mm.static_used_count[pool_id]--;
    g_mm.static_free_count[pool_id]++;
    
    block->next = g_mm.static_free_lists[pool_id];
    g_mm.static_free_lists[pool_id] = block;
    
    g_mm.total_free_count++;
    
    MM_TRACE("  Freed, size restored to %zu", block->size);
}*/

/*============================================================================
* 动态池管理函数
*============================================================================*/

/**
 * @brief 根据名称查找动态池
 * @param name 池名称
 * @return 池ID,失败返回-1
 */
static int find_dynamic_pool(const char* name) {
    for (int i = 0; i < g_mm.dynamic_pool_count; i++) {
        if (strcmp(g_mm.dynamic_pools[i].name, name) == 0) {
            return MM_POOL_CUSTOM + i;
        }
    }
    return -1;
}

/**
 * @brief 创建动态内存池
 * @param name 池名称
 * @param slot_size 槽位大小
 * @param slot_count 槽位数量
 * @param out_pool_id 输出池ID
 * @return 错误码
 */
static mm_error_t dynamic_pool_create(const char* name, size_t slot_size, size_t slot_count, int* out_pool_id) {
    dynamic_pool_t* pool;
    size_t total_size;
    uint8_t* base_ptr;
    mm_block_t* prev = NULL;
    int pool_id;
    
    /* 检查是否已存在同名池 */
    pool_id = find_dynamic_pool(name);
    if (pool_id >= 0) {
        if (out_pool_id) *out_pool_id = pool_id;
        return MM_OK;
    }
    
    /* 检查池数量是否超限 */
    if (g_mm.dynamic_pool_count >= MM_MAX_POOLS - MM_POOL_CUSTOM) {
        return MM_ERR_OUT_OF_MEMORY;
    }
    
    /* 对齐槽位大小(口诀⑥:对齐边界,性能优) */
    slot_size = (slot_size + MM_ALIGNMENT - 1) & ~(MM_ALIGNMENT - 1);
    total_size = (slot_size + sizeof(mm_block_t)) * slot_count;
    
    /* 分配内存(动态池允许malloc,但内部管理仍是固定槽位) */
    base_ptr = (uint8_t*)aligned_alloc(MM_ALIGNMENT, total_size);
    if (!base_ptr) {
        return MM_ERR_OUT_OF_MEMORY;
    }
    
    /* 初始化动态池结构 */
    pool = &g_mm.dynamic_pools[g_mm.dynamic_pool_count];
    memset(pool, 0, sizeof(dynamic_pool_t));
    
    strncpy(pool->name, name, sizeof(pool->name) - 1);
    pool->config.name = pool->name;
    pool->config.total_size = total_size;
    pool->config.slot_size = slot_size + sizeof(mm_block_t);
    pool->config.slot_count = slot_count;
    pool->config.alignment = MM_ALIGNMENT;
    pool->config.is_dynamic = 1;
    pool->base_ptr = base_ptr;
    pool->used_count = 0;
    pool->free_count = slot_count;
    pool->alloc_count = 0;
    pool->free_count_total = 0;
    pool->peak_alloc_bytes = 0;
    pthread_mutex_init(&pool->mutex, NULL);
    pool->initialized = 1;
    
    /* 分配槽位使用标志数组 */
    pool->slot_used = (uint32_t*)calloc(slot_count, sizeof(uint32_t));
    if (!pool->slot_used) {
        free(base_ptr);
        return MM_ERR_OUT_OF_MEMORY;
    }
    
    /* 构建空闲链表(口诀③:池化管理,零碎片) */
    for (size_t i = 0; i < slot_count; i++) {
        uint8_t* slot_start = base_ptr + i * (slot_size + sizeof(mm_block_t));
        mm_block_t* block = (mm_block_t*)slot_start;
        
        block->next = NULL;
        block->ref_count = 0;
        block->magic = MM_MAGIC;
        block->size = slot_size;
        block->pool_id = MM_POOL_CUSTOM + g_mm.dynamic_pool_count;
        block->slot_idx = i;
        block->alloc_line = 0;
        block->alloc_file = NULL;
        block->user_ptr = slot_start + sizeof(mm_block_t);
        
        if (prev) {
            prev->next = block;
        } else {
            pool->free_list = block;
        }
        prev = block;
    }
    
    *out_pool_id = MM_POOL_CUSTOM + g_mm.dynamic_pool_count;
    g_mm.dynamic_pool_count++;
    
    return MM_OK;
}

/*============================================================================
* 公共API实现 - 错误处理
*============================================================================*/

/**
 * @brief 获取错误码描述字符串
 * @param err 错误码
 * @return 错误描述字符串
 */
const char* mm_error_string(mm_error_t err) {
    switch (err) {
        case MM_OK: return "Success";
        case MM_ERR_INVALID_POOL: return "Invalid pool";
        case MM_ERR_OUT_OF_MEMORY: return "Out of memory";
        case MM_ERR_INVALID_PTR: return "Invalid pointer";
        case MM_ERR_SIZE_TOO_LARGE: return "Size too large for slot";
        case MM_ERR_POOL_FULL: return "Pool is full";
        case MM_ERR_NOT_INITIALIZED: return "Not initialized";
        case MM_ERR_CORRUPTED: return "Memory corrupted";
        default: return "Unknown error";
    }
}

/*============================================================================
* 公共API实现 - 初始化和销毁
*============================================================================*/

/**
 * @brief 初始化内存管理模块
 * @return 错误码
 */
mm_error_t mm_init(void) {
    pthread_mutex_lock(&g_mm.global_mutex);
    
    MM_TRACE("mm_init called, initialized=%d", g_mm.initialized);
    
    if (g_mm.initialized) {
        MM_TRACE("Already initialized");
        pthread_mutex_unlock(&g_mm.global_mutex);
        return MM_OK;
    }
    
    /* 初始化三个静态池 */
    MM_TRACE("Initializing TensorPool...");
    init_static_pool(MM_POOL_TENSOR, &g_default_configs[0], g_tensor_pool);
    
    MM_TRACE("Initializing ModelPool...");
    init_static_pool(MM_POOL_MODEL, &g_default_configs[1], g_model_pool);
    
    MM_TRACE("Initializing FramePool...");
    init_static_pool(MM_POOL_FRAME, &g_default_configs[2], g_frame_pool);
    
    g_mm.initialized = 1;
    
    MM_TRACE("mm_init completed successfully");
    
    pthread_mutex_unlock(&g_mm.global_mutex);
    
    return MM_OK;
}

/**
 * @brief 反初始化内存管理模块
 * @return 错误码
 */
mm_error_t mm_deinit(void) {
    pthread_mutex_lock(&g_mm.global_mutex);
    
    if (!g_mm.initialized) {
        pthread_mutex_unlock(&g_mm.global_mutex);
        return MM_OK;
    }
    
    /* 检测泄漏 */
    mm_check_leaks(stdout);
    
    /* 重置静态池状态 */
    for (int i = 0; i < MM_POOL_CUSTOM; i++) {
        g_mm.static_pools[i] = NULL;
        g_mm.static_free_lists[i] = NULL;
        g_mm.static_used_count[i] = 0;
        g_mm.static_free_count[i] = 0;
        g_mm.static_initialized[i] = 0;
        memset(g_mm.static_slot_used[i], 0, sizeof(g_mm.static_slot_used[i]));
    }
    
    /* 释放动态池 */
    for (int i = 0; i < g_mm.dynamic_pool_count; i++) {
        dynamic_pool_t* pool = &g_mm.dynamic_pools[i];
        if (pool->initialized) {
            if (pool->base_ptr) free(pool->base_ptr);
            if (pool->slot_used) free(pool->slot_used);
            pthread_mutex_destroy(&pool->mutex);
            pool->initialized = 0;
        }
    }
    g_mm.dynamic_pool_count = 0;
    
    g_mm.initialized = 0;
    
    pthread_mutex_unlock(&g_mm.global_mutex);
    
    return MM_OK;
}

/**
 * @brief 检查是否已初始化
 * @return true=已初始化, false=未初始化
 */
bool mm_is_initialized(void) {
    return g_mm.initialized;
}

/*============================================================================
* 公共API实现 - 内存池管理
*============================================================================*/

/**
 * @brief 创建自定义内存池
 * @param name 池名称
 * @param slot_size 槽位大小
 * @param slot_count 槽位数量
 * @param out_pool_id 输出池ID
 * @return 错误码
 */
mm_error_t mm_pool_create(const char* name, size_t slot_size, size_t slot_count, int* out_pool_id) {
    mm_error_t err;
    
    if (!name || !out_pool_id) return MM_ERR_INVALID_PTR;
    if (slot_size == 0 || slot_count == 0) return MM_ERR_INVALID_PTR;
    if (!g_mm.initialized) return MM_ERR_NOT_INITIALIZED;
    
    pthread_mutex_lock(&g_mm.global_mutex);
    err = dynamic_pool_create(name, slot_size, slot_count, out_pool_id);
    pthread_mutex_unlock(&g_mm.global_mutex);
    
    return err;
}

/**
 * @brief 销毁自定义内存池
 * @param pool_id 池ID
 * @return 错误码
 * 
 * @note 直接遍历 slot_used 数组检查泄漏,不依赖 used_count 计数器
 */
mm_error_t mm_pool_destroy(int pool_id) {
    dynamic_pool_t* pool;
    int idx;
    int has_leak = 0;
    
    /* 参数验证 */
    if (pool_id < MM_POOL_CUSTOM || pool_id >= MM_MAX_POOLS) {
        return MM_ERR_INVALID_POOL;
    }
    
    idx = pool_id - MM_POOL_CUSTOM;
    if (idx >= g_mm.dynamic_pool_count) {
        return MM_ERR_INVALID_POOL;
    }
    
    pool = &g_mm.dynamic_pools[idx];
    
    /* 关键修复:直接遍历 slot_used 数组检查泄漏,不依赖 used_count */
    for (size_t i = 0; i < pool->config.slot_count; i++) {
        if (pool->slot_used[i] != 0) {
            has_leak = 1;
            MM_ERROR("Pool %s: slot %zu still used (size=%u)", 
                     pool->name, i, pool->slot_used[i]);
        }
    }
    
    if (has_leak) {
        return MM_ERR_POOL_FULL;
    }
    
    /* 销毁资源 */
    if (pool->base_ptr) {
        free(pool->base_ptr);
        pool->base_ptr = NULL;
    }
    if (pool->slot_used) {
        free(pool->slot_used);
        pool->slot_used = NULL;
    }
    pthread_mutex_destroy(&pool->mutex);
    
    /* 移动后面的池向前,更新被移动池中所有块的 pool_id */
    for (int i = idx; i < g_mm.dynamic_pool_count - 1; i++) {
        g_mm.dynamic_pools[i] = g_mm.dynamic_pools[i + 1];
        /* 更新被移动池中所有块的 pool_id */
        dynamic_pool_t* moved_pool = &g_mm.dynamic_pools[i];
        if (moved_pool->initialized && moved_pool->base_ptr) {
            for (size_t j = 0; j < moved_pool->config.slot_count; j++) {
                uint8_t* slot_start = moved_pool->base_ptr + j * moved_pool->config.slot_size;
                mm_block_t* block = (mm_block_t*)slot_start;
                block->pool_id = MM_POOL_CUSTOM + i;
            }
        }
    }
    g_mm.dynamic_pool_count--;
    
    return MM_OK;
}

/**
 * @brief 获取预定义池ID
 * @param type 池类型
 * @return 池ID,失败返回-1
 */
int mm_pool_id(mm_pool_type_t type) {
    if (type >= MM_POOL_CUSTOM) return -1;
    return (int)type;
}

/**
 * @brief 获取池配置
 * @param pool_id 池ID
 * @param config 输出配置
 * @return 错误码
 */
mm_error_t mm_pool_config(int pool_id, mm_pool_config_t* config) {
    if (!config) return MM_ERR_INVALID_PTR;
    
    /* 静态池 */
    if (pool_id >= 0 && pool_id < MM_POOL_CUSTOM) {
        memcpy(config, &g_default_configs[pool_id], sizeof(mm_pool_config_t));
        return MM_OK;
    }
    
    /* 动态池 */
    if (pool_id >= MM_POOL_CUSTOM && pool_id < MM_MAX_POOLS) {
        int idx = pool_id - MM_POOL_CUSTOM;
        if (idx < g_mm.dynamic_pool_count) {
            memcpy(config, &g_mm.dynamic_pools[idx].config, sizeof(mm_pool_config_t));
            return MM_OK;
        }
    }
    
    return MM_ERR_INVALID_POOL;
}

/*============================================================================
* 公共API实现 - 分配释放
*============================================================================*/

/**
 * @brief 分配内存
 * @param pool_id 池ID
 * @param size 需要的大小
 * @return 内存指针,失败返回NULL
 */
void* mm_alloc(int pool_id, size_t size) {
    return mm_alloc_dbg(pool_id, size, NULL, 0);
}

/**
 * @brief 带调试信息的分配
 * @param pool_id 池ID
 * @param size 大小
 * @param file 文件名
 * @param line 行号
 * @return 内存指针,失败返回NULL
 */
void* mm_alloc_dbg(int pool_id, size_t size, const char* file, int line) {
    void* ptr = NULL;
    
    if (size == 0) return NULL;
    if (!g_mm.initialized) return NULL;
    
    /* 静态池分配 */
    if (pool_id >= 0 && pool_id < MM_POOL_CUSTOM) {
        if (!g_mm.static_initialized[pool_id]) {
            MM_ERROR("Static pool %d not initialized", pool_id);
            return NULL;
        }
        
        pthread_mutex_lock(&g_mm.global_mutex);
        ptr = static_pool_alloc(pool_id, size, file, line);
        pthread_mutex_unlock(&g_mm.global_mutex);
        
        /* 关键修复:如果分配失败,直接返回NULL */
        return ptr;
    }
    
    /* 动态池分配 */
    if (pool_id >= MM_POOL_CUSTOM && pool_id < MM_MAX_POOLS) {
        int idx = pool_id - MM_POOL_CUSTOM;
        if (idx < g_mm.dynamic_pool_count) {
            dynamic_pool_t* pool = &g_mm.dynamic_pools[idx];
            mm_block_t* block;
            
            pthread_mutex_lock(&pool->mutex);
            
            block = pool->free_list;
            if (!block) {
                pthread_mutex_unlock(&pool->mutex);
                return NULL;  /* 修复:返回NULL而不是继续 */
            }
            
            pool->free_list = block->next;
            
            pool->slot_used[block->slot_idx] = 1;
            pool->used_count++;
            pool->free_count--;
            pool->alloc_count++;
            
            size_t total_bytes = pool->used_count * pool->config.slot_size;
            if (total_bytes > pool->peak_alloc_bytes) {
                pool->peak_alloc_bytes = total_bytes;
            }
            
            block->ref_count = 1;
            block->magic = MM_MAGIC;
            block->size = size;
            block->pool_id = pool_id;
            block->alloc_line = line;
            block->alloc_file = file;
            
            ptr = block->user_ptr;
            memset(ptr, 0, size);
            
            g_mm.total_alloc_count++;
            g_mm.total_alloc_bytes += size;
            
            pthread_mutex_unlock(&pool->mutex);
            return ptr;
        }
    }
    
    return NULL;
}

/**
 * @brief 释放内存
 * @param pool_id 池ID
 * @param ptr 内存指针
 */
void mm_free(int pool_id, void* ptr) {
    mm_block_t* block;
    
    if (!ptr) return;
    if (!g_mm.initialized) return;
    
    /* 静态池释放 */
    if (pool_id >= 0 && pool_id < MM_POOL_CUSTOM) {
        if (!g_mm.static_initialized[pool_id]) return;
        if (!g_mm.static_pools[pool_id]) return;
        
        uintptr_t addr = (uintptr_t)ptr;
        uintptr_t base = (uintptr_t)g_mm.static_pools[pool_id];
        uintptr_t end = base + g_default_configs[pool_id].total_size;
        
        if (addr < base || addr >= end) {
            MM_TRACE("Pointer %p not in pool %d range", ptr, pool_id);
            return;
        }
        
        block = block_from_ptr(ptr);
        if (!block_valid(block)) {
            MM_ERROR("Invalid block at %p", ptr);
            return;
        }
        
        if (block->pool_id != pool_id) {
            MM_ERROR("Block pool_id %d != %d", block->pool_id, pool_id);
            return;
        }
        
        pthread_mutex_lock(&g_mm.global_mutex);
        
        block->ref_count = 0;
        block->alloc_line = 0;
        block->alloc_file = NULL;
        
        g_mm.static_slot_used[pool_id][block->slot_idx] = 0;
        g_mm.static_used_count[pool_id]--;
        g_mm.static_free_count[pool_id]++;
        
        /* 恢复块容量 */
        block->size = g_default_configs[pool_id].slot_size - sizeof(mm_block_t);
        block->next = g_mm.static_free_lists[pool_id];
        g_mm.static_free_lists[pool_id] = block;
        
        g_mm.total_free_count++;
        
        pthread_mutex_unlock(&g_mm.global_mutex);
        return;
    }
    
    /* 动态池释放 - 调用 dynamic_pool_free */
    if (pool_id >= MM_POOL_CUSTOM && pool_id < MM_MAX_POOLS) {
        int idx = pool_id - MM_POOL_CUSTOM;
        if (idx < g_mm.dynamic_pool_count) {
            dynamic_pool_t* pool = &g_mm.dynamic_pools[idx];
            uintptr_t addr = (uintptr_t)ptr;
            uintptr_t base = (uintptr_t)pool->base_ptr;
            uintptr_t end = base + pool->config.total_size;
            
            if (addr < base || addr >= end) {
                MM_TRACE("Pointer %p not in dynamic pool %d", ptr, pool_id);
                return;
            }
            
            /* 调用 dynamic_pool_free 函数 */
            dynamic_pool_free(pool, ptr);
            g_mm.total_free_count++;
            return;
        }
    }
}

/**
 * @brief 获取内存块大小
 * @param ptr 内存指针
 * @return 实际分配大小,失败返回0
 */
size_t mm_get_size(void* ptr) {
    mm_block_t* block;
    uintptr_t addr;
    
    if (!ptr) return 0;
    
    addr = (uintptr_t)ptr;
    
    /* 先检查指针是否在有效内存池范围内 */
    int valid = 0;
    for (int i = 0; i < MM_POOL_CUSTOM; i++) {
        if (g_mm.static_initialized[i] && g_mm.static_pools[i]) {
            uintptr_t base = (uintptr_t)g_mm.static_pools[i];
            uintptr_t end = base + g_default_configs[i].total_size;
            if (addr >= base && addr < end) {
                valid = 1;
                break;
            }
        }
    }
    
    if (!valid) {
        for (int i = 0; i < g_mm.dynamic_pool_count; i++) {
            dynamic_pool_t* pool = &g_mm.dynamic_pools[i];
            if (pool->initialized && pool->base_ptr) {
                uintptr_t base = (uintptr_t)pool->base_ptr;
                uintptr_t end = base + pool->config.total_size;
                if (addr >= base && addr < end) {
                    valid = 1;
                    break;
                }
            }
        }
    }
    
    if (!valid) {
        return 0;
    }
    
    block = block_from_ptr(ptr);
    if (!block_valid(block)) {
        return 0;
    }
    
    return block->size;
}

/**
 * @brief 获取内存块所属池ID
 * @param ptr 内存指针
 * @return 池ID,失败返回-1
 */
int mm_get_pool_id(void* ptr) {
    mm_block_t* block;
    uintptr_t addr;
    
    if (!ptr) return -1;
    
    addr = (uintptr_t)ptr;
    
    /* 先检查指针是否在有效内存池范围内 */
    for (int i = 0; i < MM_POOL_CUSTOM; i++) {
        if (g_mm.static_initialized[i] && g_mm.static_pools[i]) {
            uintptr_t base = (uintptr_t)g_mm.static_pools[i];
            uintptr_t end = base + g_default_configs[i].total_size;
            if (addr >= base && addr < end) {
                block = block_from_ptr(ptr);
                if (block_valid(block)) {
                    return block->pool_id;
                }
                return -1;
            }
        }
    }
    
    for (int i = 0; i < g_mm.dynamic_pool_count; i++) {
        dynamic_pool_t* pool = &g_mm.dynamic_pools[i];
        if (pool->initialized && pool->base_ptr) {
            uintptr_t base = (uintptr_t)pool->base_ptr;
            uintptr_t end = base + pool->config.total_size;
            if (addr >= base && addr < end) {
                block = block_from_ptr(ptr);
                if (block_valid(block)) {
                    return block->pool_id;
                }
                return -1;
            }
        }
    }
    
    return -1;
}

/*============================================================================
* 公共API实现 - 引用计数
*============================================================================*/

/**
 * @brief 增加引用计数
 * @param ptr 内存指针
 * @return 新的引用计数,失败返回-1
 */
int mm_ref(void* ptr) {
    mm_block_t* block = block_from_ptr(ptr);
    if (!block_valid(block)) return -1;
    return __sync_add_and_fetch(&block->ref_count, 1);
}

/**
 * @brief 减少引用计数
 * @param pool_id 池ID
 * @param ptr 内存指针
 * @return 新的引用计数,失败返回-1
 */
int mm_unref(int pool_id, void* ptr) {
    mm_block_t* block = block_from_ptr(ptr);
    int ref;
    
    if (!block_valid(block)) return -1;
    
    ref = __sync_sub_and_fetch(&block->ref_count, 1);
    
    if (ref == 0) {
        mm_free(pool_id, ptr);
    }
    
    return ref;
}

/**
 * @brief 获取引用计数
 * @param ptr 内存指针
 * @return 引用计数,失败返回-1
 */
int mm_refcount(void* ptr) {
    mm_block_t* block = block_from_ptr(ptr);
    if (!block_valid(block)) return -1;
    return (int)block->ref_count;
}

/*============================================================================
* 公共API实现 - 统计调试
*============================================================================*/

/**
 * @brief 获取统计信息
 * @param pool_id 池ID
 * @param stats 输出统计信息
 * @return 错误码
 */
mm_error_t mm_stats(int pool_id, mm_stats_t* stats) {
    if (!stats) return MM_ERR_INVALID_PTR;
    
    memset(stats, 0, sizeof(mm_stats_t));
    
    /* 静态池 */
    if (pool_id >= 0 && pool_id < MM_POOL_CUSTOM) {
        if (!g_mm.static_initialized[pool_id]) {
            return MM_ERR_NOT_INITIALIZED;
        }
        stats->name = g_default_configs[pool_id].name;
        stats->slot_size = g_default_configs[pool_id].slot_size;
        stats->total_slots = g_default_configs[pool_id].slot_count;
        stats->used_slots = g_mm.static_used_count[pool_id];
        stats->free_slots = g_mm.static_free_count[pool_id];
        stats->total_alloc_bytes = stats->used_slots * stats->slot_size;
        stats->peak_alloc_bytes = stats->total_alloc_bytes;
        return MM_OK;
    }
    
    /* 动态池 */
    if (pool_id >= MM_POOL_CUSTOM && pool_id < MM_MAX_POOLS) {
        int idx = pool_id - MM_POOL_CUSTOM;
        if (idx < g_mm.dynamic_pool_count) {
            dynamic_pool_t* pool = &g_mm.dynamic_pools[idx];
            
            /* 加锁读取,保证一致性 */
            pthread_mutex_lock(&pool->mutex);
            
            stats->name = pool->name;
            stats->slot_size = pool->config.slot_size;
            stats->total_slots = pool->config.slot_count;
            stats->used_slots = pool->used_count;
            stats->free_slots = pool->free_count;
            stats->total_alloc_bytes = pool->used_count * pool->config.slot_size;
            stats->peak_alloc_bytes = pool->peak_alloc_bytes;
            stats->alloc_count = pool->alloc_count;
            stats->free_count = pool->free_count_total;
            
            pthread_mutex_unlock(&pool->mutex);
            return MM_OK;
        }
    }
    
    return MM_ERR_INVALID_POOL;
}

/**
 * @brief 打印所有池状态
 * @param out 输出流
 */
void mm_dump(FILE* out) {
    mm_stats_t stats;
    
    if (!out) out = stdout;
    
    fprintf(out, "\n");
    fprintf(out, "╔════════════════════════════════════════════════════════════════════════════════╗\n");
    fprintf(out, "║                         Memory Pool Status                                     ║\n");
    fprintf(out, "╠════════════════════════════════════════════════════════════════════════════════╣\n");
    
    /* 静态池 */
    for (int i = 0; i < MM_POOL_CUSTOM; i++) {
        if (mm_stats(i, &stats) == MM_OK) {
            fprintf(out, "║ %-12s: total=%4zu KB, slots=%2zu, used=%2zu, free=%2zu, peak=%6zu KB  ║\n",
                stats.name,
                stats.total_slots * stats.slot_size / 1024,
                stats.total_slots,
                stats.used_slots,
                stats.free_slots,
                stats.peak_alloc_bytes / 1024);
        } else {
            fprintf(out, "║ %-12s: NOT INITIALIZED                                                 ║\n",
                g_default_configs[i].name);
        }
    }
    
    /* 动态池 */
    for (int i = 0; i < g_mm.dynamic_pool_count; i++) {
        int pid = MM_POOL_CUSTOM + i;
        if (mm_stats(pid, &stats) == MM_OK) {
            fprintf(out, "║ %-12s: total=%4zu KB, slots=%2zu, used=%2zu, free=%2zu, peak=%6zu KB  ║\n",
                stats.name,
                stats.total_slots * stats.slot_size / 1024,
                stats.total_slots,
                stats.used_slots,
                stats.free_slots,
                stats.peak_alloc_bytes / 1024);
        }
    }
    
    fprintf(out, "╠════════════════════════════════════════════════════════════════════════════════╣\n");
    fprintf(out, "║ Global: allocs=%llu, frees=%llu, bytes=%llu, leaks=%llu                        ║\n",
        (unsigned long long)g_mm.total_alloc_count,
        (unsigned long long)g_mm.total_free_count,
        (unsigned long long)g_mm.total_alloc_bytes,
        (unsigned long long)g_mm.total_leak_count);
    fprintf(out, "╚════════════════════════════════════════════════════════════════════════════════╝\n");
    fprintf(out, "\n");
}

/**
 * @brief 检测内存泄漏
 * @param out 输出流
 * @return 泄漏数量
 */
int mm_check_leaks(FILE* out) {
    int leak_count = 0;
    
    if (!out) out = stdout;
    
    /* 检查静态池 */
    for (int i = 0; i < MM_POOL_CUSTOM; i++) {
        if (g_mm.static_initialized[i] && g_mm.static_used_count[i] > 0) {
            leak_count += g_mm.static_used_count[i];
            fprintf(out, "[LEAK] Pool %s: %zu slots still allocated\n",
                g_default_configs[i].name,
                g_mm.static_used_count[i]);
            
            for (size_t slot = 0; slot < g_default_configs[i].slot_count; slot++) {
                if (g_mm.static_slot_used[i][slot]) {
                    uint8_t* slot_start = g_mm.static_pools[i] + slot * g_default_configs[i].slot_size;
                    mm_block_t* block = (mm_block_t*)slot_start;
                    fprintf(out, "  - Slot %zu: size=%zu, ref=%u",
                        slot, block->size, block->ref_count);
                    if (block->alloc_file) {
                        fprintf(out, ", at %s:%d", block->alloc_file, block->alloc_line);
                    }
                    fprintf(out, "\n");
                }
            }
        }
    }
    
    /* 检查动态池 */
    for (int i = 0; i < g_mm.dynamic_pool_count; i++) {
        dynamic_pool_t* pool = &g_mm.dynamic_pools[i];
        if (pool->initialized && pool->used_count > 0) {
            leak_count += pool->used_count;
            fprintf(out, "[LEAK] Pool %s: %zu slots still allocated\n",
                pool->name, pool->used_count);
            
            for (size_t slot = 0; slot < pool->config.slot_count; slot++) {
                if (pool->slot_used[slot]) {
                    uint8_t* slot_start = pool->base_ptr + slot * pool->config.slot_size;
                    mm_block_t* block = (mm_block_t*)slot_start;
                    fprintf(out, "  - Slot %zu: size=%zu, ref=%u",
                        slot, block->size, block->ref_count);
                    if (block->alloc_file) {
                        fprintf(out, ", at %s:%d", block->alloc_file, block->alloc_line);
                    }
                    fprintf(out, "\n");
                }
            }
        }
    }
    
    g_mm.total_leak_count = leak_count;
    
    return leak_count;
}

/**
 * @brief 打印内存块信息
 * @param ptr 内存指针
 * @param out 输出流
 */
void mm_dump_block(void* ptr, FILE* out) {
    mm_block_t* block;
    
    if (!out) out = stdout;
    
    if (!ptr) {
        fprintf(out, "mm_dump_block: NULL pointer\n");
        return;
    }
    
    block = block_from_ptr(ptr);
    
    if (!block_valid(block)) {
        fprintf(out, "mm_dump_block: Invalid block at %p\n", ptr);
        return;
    }
    
    fprintf(out, "Block at %p:\n", ptr);
    fprintf(out, "  pool_id: %d\n", block->pool_id);
    fprintf(out, "  slot_idx: %u\n", block->slot_idx);
    fprintf(out, "  size: %zu bytes\n", block->size);
    fprintf(out, "  ref_count: %u\n", block->ref_count);
    fprintf(out, "  magic: 0x%08X %s\n", block->magic, 
        block->magic == MM_MAGIC ? "(OK)" : "(CORRUPTED)");
    if (block->alloc_file) {
        fprintf(out, "  allocated: %s:%d\n", block->alloc_file, block->alloc_line);
    }
}

/**
 * @brief 重置静态池
 * @param pool_id 池ID
 */
/*static void static_pool_reset(int pool_id) {
    size_t slot_size = g_default_configs[pool_id].slot_size;
    size_t slot_count = g_default_configs[pool_id].slot_count;
    mm_block_t* prev = NULL;
    uint8_t* base_ptr = g_mm.static_pools[pool_id];
    
    if (!base_ptr) return;
    
    g_mm.static_used_count[pool_id] = 0;
    g_mm.static_free_count[pool_id] = slot_count;
    memset(g_mm.static_slot_used[pool_id], 0, sizeof(g_mm.static_slot_used[pool_id]));
    
    for (size_t i = 0; i < slot_count; i++) {
        uint8_t* slot_start = base_ptr + i * slot_size;
        mm_block_t* block = (mm_block_t*)slot_start;
        
        block->next = NULL;
        block->ref_count = 0;
        block->magic = MM_MAGIC;
        block->size = slot_size - sizeof(mm_block_t);
        block->pool_id = pool_id;
        block->slot_idx = i;
        block->alloc_line = 0;
        block->alloc_file = NULL;
        block->user_ptr = (uint8_t*)slot_start + sizeof(mm_block_t);
        
        if (prev) {
            prev->next = block;
        } else {
            g_mm.static_free_lists[pool_id] = block;
        }
        prev = block;
    }
}*/

/**
 * @brief 重置所有内存池
 */
void mm_reset_all(void) {
    if (!g_mm.initialized) return;
    
    MM_TRACE("Resetting all memory pools");
    
    /* 重置静态池 */
    for (int i = 0; i < MM_POOL_CUSTOM; i++) {
        if (g_mm.static_initialized[i] && g_mm.static_pools[i]) {
            size_t slot_size = g_default_configs[i].slot_size;
            size_t slot_count = g_default_configs[i].slot_count;
            mm_block_t* prev = NULL;
            uint8_t* base_ptr = g_mm.static_pools[i];
            
            g_mm.static_used_count[i] = 0;
            g_mm.static_free_count[i] = slot_count;
            memset(g_mm.static_slot_used[i], 0, sizeof(g_mm.static_slot_used[i]));
            
            for (size_t j = 0; j < slot_count; j++) {
                uint8_t* slot_start = base_ptr + j * slot_size;
                mm_block_t* block = (mm_block_t*)slot_start;
                
                block->next = NULL;
                block->ref_count = 0;
                block->magic = MM_MAGIC;
                block->size = slot_size - sizeof(mm_block_t);
                block->pool_id = i;
                block->slot_idx = j;
                block->alloc_line = 0;
                block->alloc_file = NULL;
                block->user_ptr = (uint8_t*)slot_start + sizeof(mm_block_t);
                
                if (prev) {
                    prev->next = block;
                } else {
                    g_mm.static_free_lists[i] = block;
                }
                prev = block;
            }
            MM_TRACE("Reset static pool %d (%s)", i, g_default_configs[i].name);
        }
    }
    
    /* 重置动态池 */
    for (int i = 0; i < g_mm.dynamic_pool_count; i++) {
        dynamic_pool_t* pool = &g_mm.dynamic_pools[i];
        if (pool->initialized && pool->base_ptr) {
            size_t slot_size = pool->config.slot_size;
            size_t slot_count = pool->config.slot_count;
            mm_block_t* prev = NULL;
            
            pool->used_count = 0;
            pool->free_count = slot_count;
            if (pool->slot_used) {
                memset(pool->slot_used, 0, slot_count * sizeof(uint32_t));
            }
            pool->alloc_count = 0;
            pool->free_count_total = 0;
            pool->peak_alloc_bytes = 0;
            
            for (size_t j = 0; j < slot_count; j++) {
                uint8_t* slot_start = pool->base_ptr + j * slot_size;
                mm_block_t* block = (mm_block_t*)slot_start;
                
                block->next = NULL;
                block->ref_count = 0;
                block->magic = MM_MAGIC;
                block->size = slot_size - sizeof(mm_block_t);
                /* 关键修复:更新 pool_id 为当前索引 */
                block->pool_id = MM_POOL_CUSTOM + i;
                block->slot_idx = j;
                block->alloc_line = 0;
                block->alloc_file = NULL;
                block->user_ptr = (uint8_t*)slot_start + sizeof(mm_block_t);
                
                if (prev) {
                    prev->next = block;
                } else {
                    pool->free_list = block;
                }
                prev = block;
            }
            MM_TRACE("Reset dynamic pool %d (%s)", i, pool->name);
        }
    }
    
    /* 重置全局统计 */
    g_mm.total_alloc_count = 0;
    g_mm.total_free_count = 0;
    g_mm.total_alloc_bytes = 0;
    g_mm.total_leak_count = 0;
    
    MM_TRACE("All pools reset complete");
}

3. Makefile

#=============================================================================
# Makefile for Memory Manager Module
#=============================================================================

CC = gcc
AR = ar
CFLAGS = -Wall -Wextra -O2 -g -fPIC -DMM_DEBUG=1
INCLUDES = -I./include
LDFLAGS = -lpthread

# 目标文件
TARGET_LIB = libmm.a
TARGET_SO = libmm.so
TARGET_TEST = test_mm

# 源文件
SRC_DIR = src
OBJ_DIR = obj
SRCS = $(wildcard $(SRC_DIR)/*.c)
OBJS = $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRCS))

# 测试源文件
TEST_SRC = tests/test_mm.c
TEST_OBJ = $(OBJ_DIR)/test_mm.o

#=============================================================================
# 目标规则
#=============================================================================

.PHONY: all clean test install

all: $(TARGET_LIB) $(TARGET_SO) $(TARGET_TEST)

$(OBJ_DIR):
	mkdir -p $(OBJ_DIR)

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

$(TARGET_LIB): $(OBJS)
	$(AR) rcs $@ $^

$(TARGET_SO): $(OBJS)
	$(CC) -shared -o $@ $^ $(LDFLAGS)

$(TEST_OBJ): $(TEST_SRC) | $(OBJ_DIR)
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

$(TARGET_TEST): $(OBJS) $(TEST_OBJ)
	$(CC) -o $@ $^ $(LDFLAGS)

test: $(TARGET_TEST)
	./$(TARGET_TEST)

clean:
	rm -rf $(OBJ_DIR)
	rm -f $(TARGET_LIB) $(TARGET_SO) $(TARGET_TEST)

install: $(TARGET_LIB) $(TARGET_SO)
	mkdir -p $(DESTDIR)/usr/lib
	mkdir -p $(DESTDIR)/usr/include
	cp $(TARGET_LIB) $(DESTDIR)/usr/lib/
	cp $(TARGET_SO) $(DESTDIR)/usr/lib/
	cp include/mm.h $(DESTDIR)/usr/include/
	

4. 内存管理七字诀实现对照表

口诀 实现位置 说明
① 预分配,不动态 g_tensor_pool[512*1024] 编译时分配静态数组
② 定大小,不分片 slot_size = 64KB 每个槽位固定大小
③ 池化管理,零碎片 free_list 链表 固定槽位复用
④ 谁申请,谁释放 mm_alloc()/mm_free() 配对使用
⑤ 引用计数,防泄漏 ref_count 字段 自动管理,为0时释放
⑥ 对齐边界,性能优 __attribute__((aligned(64))) 64字节对齐
⑦ 栈优先,堆次之 MM_STACK_ARRAY 小数组用栈
⑧ 静态区,放常量 g_default_configs[] 配置常量放在只读段

5. 测试程序

/**
 * @file test_mm.c
 * @brief 内存管理模块单元测试 - 每个测试独立运行
 */
​
#include "mm.h"
#include <stdio.h>
#include <string.h>
​
/*============================================================================
* 测试辅助宏
*============================================================================*/
​
#define TEST_START(name) \
    printf("\n╔════════════════════════════════════════════════════════════════╗\n"); \
    printf("║ Test: %-50s ║\n", name); \
    printf("╚════════════════════════════════════════════════════════════════╝\n")
​
#define TEST_ASSERT(cond, msg) \
    do { \
        if (!(cond)) { \
            printf("  ✗ FAILED: %s\n", msg); \
            return -1; \
        } \
    } while (0)
​
#define TEST_PASS() \
    printf("  ✓ PASSED\n"); \
    return 0
​
/*============================================================================
* 测试前置/后置处理
*============================================================================*/
​
/**
 * @brief 每个测试前的准备:重置所有池
 */
static void test_setup(void) {
    /* 确保 mm_init 已调用 */
    static int init_done = 0;
    if (!init_done) {
        mm_init();
        init_done = 1;
    }
    /* 重置所有池,清空状态 */
    mm_reset_all();
}
​
/**
 * @brief 每个测试后的清理:重置所有池
 */
static void test_teardown(void) {
    mm_reset_all();
}
​
/*============================================================================
* 测试用例1: 初始化和反初始化
*============================================================================*/
​
static int test_init_deinit(void) {
    mm_error_t err;
    
    TEST_START("Initialization and Deinitialization");
    
    test_setup();
    
    err = mm_init();
    TEST_ASSERT(err == MM_OK, "mm_init failed");
    TEST_ASSERT(mm_is_initialized() == 1, "mm_is_initialized should return true");
    
    err = mm_init();
    TEST_ASSERT(err == MM_OK, "Double init should succeed");
    
    mm_deinit();
    TEST_ASSERT(mm_is_initialized() == 0, "mm_is_initialized should return false");
    
    mm_deinit();
    TEST_ASSERT(mm_is_initialized() == 0, "Double deinit should be safe");
    
    mm_init();
    
    test_teardown();
    TEST_PASS();
}
​
/*============================================================================
* 测试用例2: 预定义池分配和释放
*============================================================================*/
​
static int test_predefined_pool_alloc_free(void) {
    void* p1, *p2, *p3;
    mm_error_t err;
    mm_stats_t stats;
    
    TEST_START("Predefined Pool - Alloc/Free");
    
    test_setup();
    mm_init();
    
    p1 = mm_alloc(MM_POOL_TENSOR, 1024);
    TEST_ASSERT(p1 != NULL, "Alloc 1KB from TensorPool failed");
    
    p2 = mm_alloc(MM_POOL_TENSOR, 2048);
    TEST_ASSERT(p2 != NULL, "Alloc 2KB from TensorPool failed");
    
    p3 = mm_alloc(MM_POOL_TENSOR, 4096);
    TEST_ASSERT(p3 != NULL, "Alloc 4KB from TensorPool failed");
    
    TEST_ASSERT(mm_get_size(p1) == 1024, "Wrong size for p1");
    TEST_ASSERT(mm_get_size(p2) == 2048, "Wrong size for p2");
    TEST_ASSERT(mm_get_size(p3) == 4096, "Wrong size for p3");
    
    TEST_ASSERT(mm_get_pool_id(p1) == MM_POOL_TENSOR, "Wrong pool ID for p1");
    
    err = mm_stats(MM_POOL_TENSOR, &stats);
    TEST_ASSERT(err == MM_OK, "mm_stats failed");
    TEST_ASSERT(stats.used_slots == 3, "Used slots should be 3");
    
    mm_free(MM_POOL_TENSOR, p3);
    mm_free(MM_POOL_TENSOR, p2);
    mm_free(MM_POOL_TENSOR, p1);
    
    err = mm_stats(MM_POOL_TENSOR, &stats);
    TEST_ASSERT(err == MM_OK, "mm_stats failed");
    TEST_ASSERT(stats.used_slots == 0, "Used slots should be 0 after free");
    
    test_teardown();
    TEST_PASS();
}
​
/*============================================================================
* 测试用例3: 池满处理
*============================================================================*/
​
static int test_pool_full(void) {
    void* slots[10];
    int i;
    mm_stats_t stats;
    
    TEST_START("Pool Full Handling");
    
    test_setup();
    mm_init();
    
    for (i = 0; i < 8; i++) {
        slots[i] = mm_alloc(MM_POOL_TENSOR, 1024);
        if (slots[i] == NULL) {
            printf("  ✗ FAILED: Alloc %d failed\n", i);
            test_teardown();
            return -1;
        }
    }
    
    void* p = mm_alloc(MM_POOL_TENSOR, 1024);
    TEST_ASSERT(p == NULL, "Alloc should fail when pool is full");
    
    mm_free(MM_POOL_TENSOR, slots[0]);
    p = mm_alloc(MM_POOL_TENSOR, 1024);
    TEST_ASSERT(p != NULL, "Alloc after free should succeed");
    
    mm_free(MM_POOL_TENSOR, p);
    for (i = 1; i < 8; i++) {
        mm_free(MM_POOL_TENSOR, slots[i]);
    }
    
    mm_stats(MM_POOL_TENSOR, &stats);
    TEST_ASSERT(stats.used_slots == 0, "All slots should be free");
    
    test_teardown();
    TEST_PASS();
}
​
/*============================================================================
* 测试用例4: 引用计数
*============================================================================*/
​
static int test_refcount(void) {
    void* p;
    int ref;
    mm_stats_t stats;
    
    TEST_START("Reference Count");
    
    test_setup();
    mm_init();
    
    p = mm_alloc(MM_POOL_TENSOR, 1024);
    TEST_ASSERT(p != NULL, "Alloc failed");
    
    ref = mm_refcount(p);
    TEST_ASSERT(ref == 1, "Initial refcount should be 1");
    
    ref = mm_ref(p);
    TEST_ASSERT(ref == 2, "After ref, refcount should be 2");
    
    ref = mm_ref(p);
    TEST_ASSERT(ref == 3, "After second ref, refcount should be 3");
    
    ref = mm_unref(MM_POOL_TENSOR, p);
    TEST_ASSERT(ref == 2, "After unref, refcount should be 2");
    
    ref = mm_unref(MM_POOL_TENSOR, p);
    TEST_ASSERT(ref == 1, "After second unref, refcount should be 1");
    
    ref = mm_unref(MM_POOL_TENSOR, p);
    TEST_ASSERT(ref == 0, "After third unref, refcount should be 0");
    
    p = NULL;
    
    mm_stats(MM_POOL_TENSOR, &stats);
    TEST_ASSERT(stats.used_slots == 0, "Memory should be freed");
    
    test_teardown();
    TEST_PASS();
}
​
/**
 * @brief 测试动态池创建和使用
 */
static int test_dynamic_pool(void) {
    int pool_id;
    mm_error_t err;
    void* p1, *p2;
    mm_stats_t stats;
    
    TEST_START("Dynamic Pool Creation");
    
    test_setup();
    mm_init();
    
    err = mm_pool_create("TestPool", 16384, 4, &pool_id);
    TEST_ASSERT(err == MM_OK, "mm_pool_create failed");
    TEST_ASSERT(pool_id >= MM_POOL_CUSTOM, "Invalid pool ID");
    
    p1 = mm_alloc(pool_id, 8192);
    TEST_ASSERT(p1 != NULL, "Alloc from dynamic pool failed");
    
    p2 = mm_alloc(pool_id, 4096);
    TEST_ASSERT(p2 != NULL, "Second alloc from dynamic pool failed");
    
    err = mm_stats(pool_id, &stats);
    TEST_ASSERT(err == MM_OK, "mm_stats failed");
    TEST_ASSERT(stats.used_slots == 2, "Used slots should be 2");
    TEST_ASSERT(stats.total_slots == 4, "Total slots should be 4");
    
    /* 释放分配的内存 */
    mm_free(pool_id, p1);
    mm_free(pool_id, p2);
    
    /* 验证池已空 */
    err = mm_stats(pool_id, &stats);
    TEST_ASSERT(err == MM_OK, "mm_stats failed");
    TEST_ASSERT(stats.used_slots == 0, "Pool should be empty before destroy");
    
    /* 销毁池 */
    err = mm_pool_destroy(pool_id);
    TEST_ASSERT(err == MM_OK, "mm_pool_destroy failed");
    
    test_teardown();
    TEST_PASS();
}
​
/*============================================================================
* 测试用例6: 内存对齐检查
*============================================================================*/
​
static int test_alignment(void) {
    void* p;
    int i;
    
    TEST_START("Memory Alignment");
    
    test_setup();
    mm_init();
    
    size_t sizes[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096};
    int num_sizes = sizeof(sizes) / sizeof(sizes[0]);
    
    for (i = 0; i < num_sizes; i++) {
        p = mm_alloc(MM_POOL_TENSOR, sizes[i]);
        if (p == NULL) {
            printf("  ✗ FAILED: Alloc %zu failed\n", sizes[i]);
            test_teardown();
            return -1;
        }
        
        uintptr_t addr = (uintptr_t)p;
        if ((addr & (MM_ALIGNMENT - 1)) != 0) {
            printf("  ✗ FAILED: Memory not aligned: %p (size=%zu)\n", p, sizes[i]);
            mm_free(MM_POOL_TENSOR, p);
            test_teardown();
            return -1;
        }
        
        mm_free(MM_POOL_TENSOR, p);
    }
    
    test_teardown();
    TEST_PASS();
}
​
/*============================================================================
* 测试用例7: 内存统计和转储
*============================================================================*/
​
static int test_stats_dump(void) {
    void* p1, *p2;
    mm_stats_t stats;
    
    TEST_START("Statistics and Dump");
    
    test_setup();
    mm_init();
    
    p1 = mm_alloc(MM_POOL_TENSOR, 1024);
    TEST_ASSERT(p1 != NULL, "Alloc from TensorPool failed");
    
    p2 = mm_alloc(MM_POOL_MODEL, 65536);
    TEST_ASSERT(p2 != NULL, "Alloc from ModelPool failed");
    
    mm_stats(MM_POOL_TENSOR, &stats);
    TEST_ASSERT(stats.used_slots == 1, "TensorPool used slots should be 1");
    TEST_ASSERT(stats.free_slots == 7, "TensorPool free slots should be 7");
    
    mm_stats(MM_POOL_MODEL, &stats);
    TEST_ASSERT(stats.used_slots == 1, "ModelPool used slots should be 1");
    TEST_ASSERT(stats.free_slots == 3, "ModelPool free slots should be 3");
    
    mm_dump(stdout);
    
    mm_free(MM_POOL_TENSOR, p1);
    mm_free(MM_POOL_MODEL, p2);
    
    test_teardown();
    TEST_PASS();
}
​
/*============================================================================
* 测试用例8: 内存泄漏检测
*============================================================================*/
​
static int test_leak_detection(void) {
    void* p;
    int leaks;
    
    TEST_START("Leak Detection");
    
    test_setup();
    mm_init();
    
    /* 分配内存但不释放 */
    p = mm_alloc(MM_POOL_TENSOR, 1024);
    TEST_ASSERT(p != NULL, "Alloc failed");
    
    /* 检测泄漏 - 应该只检测到1个 */
    leaks = mm_check_leaks(stdout);
    if (leaks != 1) {
        printf("  ✗ FAILED: Should detect 1 leak, got %d\n", leaks);
        mm_free(MM_POOL_TENSOR, p);
        test_teardown();
        return -1;
    }
    
    /* 释放内存 */
    mm_free(MM_POOL_TENSOR, p);
    
    /* 再次检测 - 应该没有泄漏 */
    leaks = mm_check_leaks(stdout);
    if (leaks != 0) {
        printf("  ✗ FAILED: Should detect 0 leaks, got %d\n", leaks);
        test_teardown();
        return -1;
    }
    
    test_teardown();
    TEST_PASS();
}
​
/**
 * @brief 测试错误处理
 */
static int test_error_handling(void) {
    void* p;
    size_t sz;
    
    TEST_START("Error Handling");
    
    test_setup();
    mm_init();
    
    /* 测试无效池ID - 应该返回NULL */
    p = mm_alloc(999, 1024);
    TEST_ASSERT(p == NULL, "Alloc with invalid pool should return NULL");
    
    /* 测试释放无效指针 - 应该安全,不崩溃 */
    mm_free(MM_POOL_TENSOR, (void*)0x1234);
    mm_free(MM_POOL_TENSOR, NULL);
    
    /* 测试分配超过槽位大小 - 应该返回NULL,不是段错误 */
    p = mm_alloc(MM_POOL_TENSOR, 128 * 1024);
    TEST_ASSERT(p == NULL, "Alloc larger than slot size should return NULL");
    
    /* 测试获取无效指针的大小 */
    sz = mm_get_size((void*)0x1234);
    TEST_ASSERT(sz == 0, "mm_get_size on invalid pointer should return 0");
    
    /* 测试获取无效指针的池ID */
    int pid = mm_get_pool_id((void*)0x1234);
    TEST_ASSERT(pid == -1, "mm_get_pool_id on invalid pointer should return -1");
    
    test_teardown();
    TEST_PASS();
}
​
/*============================================================================
* 测试用例10: 栈内存宏
*============================================================================*/
​
static int test_stack_macros(void) {
    int i;
    
    TEST_START("Stack Memory Macros");  
    test_setup();  
    MM_STACK_ARRAY(int, arr, 256);
    for (i = 0; i < 256; i++) {
        arr[i] = i;
    }
    if (arr[0] != 0 || arr[255] != 255) {
        printf("  ✗ FAILED: Stack array initialization failed\n");
        test_teardown();
        return -1;
    }
    
    MM_STACK_INIT(float, farr, 128, 3.14f);
    for (i = 0; i < 128; i++) {
        if (farr[i] != 3.14f) {
            printf("  ✗ FAILED: Stack init failed at index %d\n", i);
            test_teardown();
            return -1;
        }
    }
    
    test_teardown();
    TEST_PASS();
}
​
/*============================================================================
* 主函数
*============================================================================*/
​
int main(void) {
    int passed = 0;
    int failed = 0;
    
    printf("\n");
    printf("╔════════════════════════════════════════════════════════════════╗\n");
    printf("║           Memory Manager Module Unit Tests                     ║\n");
    printf("║           Memory Management Seven-Character Rhyme              ║\n");
    printf("╚════════════════════════════════════════════════════════════════╝\n");
    
    /* 初始化一次 */
    mm_init();
    
    #define RUN_TEST(test) \
        do { \
            int ret = test(); \
            if (ret == 0) passed++; \
            else failed++; \
        } while (0)
    
    RUN_TEST(test_init_deinit);
    RUN_TEST(test_predefined_pool_alloc_free);
    RUN_TEST(test_pool_full);
    RUN_TEST(test_refcount);
    RUN_TEST(test_dynamic_pool);
    RUN_TEST(test_alignment);
    RUN_TEST(test_stats_dump);
    RUN_TEST(test_leak_detection);
    RUN_TEST(test_error_handling);
    RUN_TEST(test_stack_macros);
    
    printf("\n");
    printf("╔════════════════════════════════════════════════════════════════╗\n");
    printf("║                       Test Summary                              ║\n");
    printf("╠════════════════════════════════════════════════════════════════╣\n");
    printf("║  Passed: %2d                                                      ║\n", passed);
    printf("║  Failed: %2d                                                      ║\n", failed);
    printf("╚════════════════════════════════════════════════════════════════╝\n");
    
    mm_deinit();
    
    return failed > 0 ? 1 : 0;
}
​
运行结果:

第二部分 内存管理模块设计与实现分析

一、项目背景与设计动机

项目场景:为什么要在项目中自己实现一个内存管理模块,而不是直接使用 malloc/free?

思路:

嵌入式 Linux 项目中,需要运行 AI 推理任务。这个场景有几个特殊要求:

  1. 实时性要求:AI 推理需要稳定的延迟,通常在 30-50ms 内完成。malloc/free 的不确定性(可能触发系统调用、内存碎片导致分配变慢)会破坏实时性。

  2. 内存受限:嵌入式设备内存有限(通常 1-2GB),频繁的 malloc/free 会产生内存碎片,长时间运行后可能出现"有足够总内存但无法分配连续大块"的情况。

  3. 确定性分配:AI 推理中张量大小是固定的(如 224x224x3 的输入),因此希望分配时间恒定,不随运行时间变化。

  4. 共享内存需求:多个模块可能需要共享同一块张量数据(如预处理模块和推理模块),需要引用计数来管理生命周期。

基于这些考虑,需要设计了这个预分配、固定槽位、引用计数的内存管理模块。


二、内存管理七字诀的由来

项目场景:"内存管理七字诀"是从哪里来?

思路:

这七字诀是在嵌入式开发中总结的经验,每一条对应一个具体的实践原则:

╔═══════════════════════════════════════════════════════════════════════════════╗
║                        内存管理七字诀                                         ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║                                                                               ║
║   ① 预分配,不动态    ② 定大小,不分片    ③ 池化管理,零碎片                 ║
║   ④ 谁申请,谁释放    ⑤ 引用计数,防泄漏    ⑥ 对齐边界,性能优               ║
║   ⑦ 栈优先,堆次之    ⑧ 静态区,放常量                                       ║
║                                                                               ║
╚═══════════════════════════════════════════════════════════════════════════════╝

逐条解释:

口诀 含义 实现方式
① 预分配,不动态 内存池在编译时或初始化时一次性分配,运行时不再申请新内存 static uint8_t g_tensor_pool[512*1024] 静态数组
② 定大小,不分片 每个池的槽位大小固定,避免内存碎片 slot_size = 64KB,每个槽位固定
③ 池化管理,零碎片 使用槽位池管理,分配释放都在池内进行,无外部碎片 free_list 空闲链表管理固定槽位
④ 谁申请,谁释放 明确内存所有权,申请者负责释放 mm_alloc() / mm_free() 配对使用
⑤ 引用计数,防泄漏 支持引用计数,多个使用者共享时自动管理 ref_count 字段,为0时自动释放
⑥ 对齐边界,性能优 内存按64字节对齐,缓存友好,适合SIMD指令 __attribute__((aligned(64)))
⑦ 栈优先,堆次之 小对象用栈,大对象用池 MM_STACK_ARRAY
⑧ 静态区,放常量 配置信息放在只读数据段 g_default_configs[] 静态常量

三、核心数据结构与流程图

项目场景:内存管理的核心数据结构和分配释放流程图

思路:

3.1 核心数据结构图
┌─────────────────────────────────────────────────────────────────────────────────┐
│                              全局内存池布局                                      │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  g_tensor_pool[512KB]        g_model_pool[1MB]         g_frame_pool[256KB]     │
│  ┌─────────────────────┐     ┌─────────────────────┐   ┌─────────────────────┐  │
│  │ Slot 0  (64KB)      │     │ Slot 0  (256KB)     │   │ Slot 0  (64KB)      │  │
│  │ ┌─────────────────┐ │     │ ┌─────────────────┐ │   │ ┌─────────────────┐ │  │
│  │ │ mm_block_t      │ │     │ │ mm_block_t      │ │   │ │ mm_block_t      │ │  │
│  │ │ (64 bytes)      │ │     │ │ (64 bytes)      │ │   │ │ (64 bytes)      │ │  │
│  │ ├─────────────────┤ │     │ ├─────────────────┤ │   │ ├─────────────────┤ │  │
│  │ │ user_data       │ │     │ │ user_data       │ │   │ │ user_data       │ │  │
│  │ │ (65472 bytes)   │ │     │ │ (262080 bytes)  │ │   │ │ (65472 bytes)   │ │  │
│  │ └─────────────────┘ │     │ └─────────────────┘ │   │ └─────────────────┘ │  │
│  ├─────────────────────┤     ├─────────────────────┤   ├─────────────────────┤  │
│  │ Slot 1  (64KB)      │     │ Slot 1  (256KB)     │   │ Slot 1  (64KB)      │  │
│  │ ...                 │     │ ...                 │   │ ...                 │  │
│  └─────────────────────┘     └─────────────────────┘   └─────────────────────┘  │
│                                                                                 │
│  mm_block_t 结构 (64字节对齐):                                                   │
│  ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐    │
│  │ next   │ref_count│ magic  │  size  │pool_id │slot_idx│alloc_line│user_ptr│    │
│  │ 8字节  │ 4字节  │ 4字节  │ 8字节  │ 4字节  │ 4字节  │ 4字节   │ 8字节  │    │
│  └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘    │
│                                      ↑                                         │
│                             64字节对齐,填充到64字节                            │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘
3.2 分配流程图
┌─────────────────────────────────────────────────────────────────────────────────┐
│                           内存分配流程 (mm_alloc)                               │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  开始: mm_alloc(pool_id, size)                                                  │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 1. 参数验证                                                              │   │
│  │    - size == 0? → 返回 NULL                                              │   │
│  │    - 模块未初始化? → 返回 NULL                                           │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 2. 根据 pool_id 选择池                                                   │   │
│  │    ├── pool_id < MM_POOL_CUSTOM → 静态池                                 │   │
│  │    └── pool_id >= MM_POOL_CUSTOM → 动态池                                │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 3. 从空闲链表取块                                                         │   │
│  │    block = free_list                                                     │   │
│  │    if (block == NULL) → 返回 NULL (池满)                                 │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 4. 检查大小                                                               │   │
│  │    if (size > block->size) → 返回 NULL (超过槽位容量)                     │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 5. 更新池状态                                                             │   │
│  │    - free_list = block->next                                             │   │
│  │    - slot_used[slot_idx] = 1                                             │   │
│  │    - used_count++                                                         │   │
│  │    - free_count--                                                         │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 6. 初始化块头部                                                           │   │
│  │    - block->ref_count = 1                                                │   │
│  │    - block->size = size (保存请求大小)                                    │   │
│  │    - block->magic = MM_MAGIC                                             │   │
│  │    - memset(user_ptr, 0, size)                                           │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  返回 user_ptr                                                                  │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘
3.3 释放流程图
┌─────────────────────────────────────────────────────────────────────────────────┐
│                           内存释放流程 (mm_free)                                │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  开始: mm_free(pool_id, ptr)                                                    │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 1. 参数验证                                                              │   │
│  │    - ptr == NULL? → 返回                                                 │   │
│  │    - 模块未初始化? → 返回                                                │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 2. 验证指针范围                                                           │   │
│  │    - 检查 ptr 是否在池的地址范围内                                         │   │
│  │    - 不在范围内 → 返回 (安全)                                             │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 3. 获取块头部并验证                                                       │   │
│  │    block = ptr - sizeof(mm_block_t)                                      │   │
│  │    if (block->magic != MM_MAGIC) → 返回 (无效块)                          │   │
│  │    if (block->pool_id != pool_id) → 返回 (不属于此池)                     │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 4. 检查双重释放                                                           │   │
│  │    if (slot_used[slot_idx] == 0) → 返回 (已释放)                          │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 5. 更新池状态                                                             │   │
│  │    - slot_used[slot_idx] = 0                                             │   │
│  │    - used_count--                                                         │   │
│  │    - free_count++                                                         │   │
│  │    - block->size = 槽位容量 (恢复为完整容量)                               │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 6. 加入空闲链表                                                           │   │
│  │    block->next = free_list                                               │   │
│  │    free_list = block                                                     │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│       │                                                                         │
│       ▼                                                                         │
│  返回                                                                           │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

四、适用场景分析

项目场景:这个内存管理模块适合哪些场景?不适合哪些场景?

思路:

4.1 适合的场景
场景 原因 示例
嵌入式AI推理 张量大小固定,预分配可避免碎片 RK3576 NPU推理
实时系统 分配时间确定,无系统调用 工业控制、自动驾驶
多媒体处理 帧缓冲区大小固定 视频解码、图像处理
长时间运行服务 无内存碎片,可稳定运行数月 监控系统、服务器
多模块共享数据 引用计数自动管理生命周期 预处理→推理→后处理流水线
4.2 不适合的场景
场景 原因 替代方案
大小不固定的动态数据 槽位大小固定,无法分配大于槽位的数据 使用 malloc/free 或变长池
大量小对象分配 槽位较大,浪费内存 使用 slab 分配器
需要动态扩容 池大小在编译时确定 使用动态池 + 链表
跨进程共享内存 本模块设计为单进程内使用 使用共享内存 + 信号量
内存需求变化大的应用 预分配可能浪费或不足 使用堆分配器

五、可扩展性设计

项目场景:如果要扩展这个模块,支持更多功能,会怎么设计?

思路:

5.1 扩展点1:新增池类型
/* 在 mm.h 中添加新的池类型 */
typedef enum {
    MM_POOL_TENSOR = 0,
    MM_POOL_MODEL  = 1,
    MM_POOL_FRAME  = 2,
    MM_POOL_BUFFER = 3,     /* 新增:通用缓冲区池 */
    MM_POOL_CUSTOM = 4,
} mm_pool_type_t;
​
/* 在 mm.c 中添加配置 */
static const mm_pool_config_t g_default_configs[] = {
    [MM_POOL_BUFFER] = {
        .name = "BufferPool",
        .total_size = 256 * 1024,
        .slot_size = 32 * 1024,
        .slot_count = 8,
        .alignment = MM_ALIGNMENT,
        .is_dynamic = 0,
    },
    /* ... */
};
5.2 扩展点2:支持变长槽位
/* 在 mm_pool_create 中增加标志位 */
mm_error_t mm_pool_create(const char* name, size_t slot_size, 
                          size_t slot_count, int flags, int* out_pool_id);
​
/* flags 定义 */
#define MM_POOL_FIXED_SIZE  0x00  /* 固定大小槽位 */
#define MM_POOL_VARIABLE    0x01  /* 变长槽位 (使用最佳匹配算法) */
#define MM_POOL_GROWABLE    0x02  /* 可扩容池 */
5.3 扩展点3:支持内存统计导出
/* 导出 JSON 格式统计 */
char* mm_stats_export_json(void);
​
/* 示例输出 */
{
    "pools": [
        {
            "name": "TensorPool",
            "total_slots": 8,
            "used_slots": 3,
            "free_slots": 5,
            "total_bytes": 524288,
            "used_bytes": 196608
        }
    ],
    "global": {
        "total_allocs": 1024,
        "total_frees": 1000,
        "current_leaks": 24
    }
}
5.4 扩展点4:支持内存池快照和恢复
/* 保存当前状态 */
mm_error_t mm_snapshot(const char* path);
​
/* 从快照恢复 (用于调试) */
mm_error_t mm_restore(const char* path);
5.5 扩展点5:支持线程局部池
/* 创建线程局部池 */
mm_error_t mm_tls_pool_create(const char* name, size_t slot_size, 
                               size_t slot_count, int* out_pool_id);
​
/* 获取当前线程的池 */
mm_error_t mm_tls_pool_get(const char* name, int* out_pool_id);

六、设计权衡与取舍

项目场景:为什么选择这个方案而不是其他?

思路:

权衡点 选择 理由
固定槽位 vs 变长槽位 固定槽位 简单、无碎片、分配时间O(1);牺牲了灵活性
静态池 vs 动态池 两者都支持 核心数据用静态池,可选动态池扩展
引用计数 vs 手动释放 引用计数 避免共享数据的双重释放问题
64字节对齐 vs 默认对齐 64字节对齐 适合NEON/SIMD指令,缓存友好
全局锁 vs 无锁 池级锁 简化实现,嵌入式单线程场景够用
内存池大小 编译时固定 嵌入式系统内存确定,避免运行时决策

七、测试策略

项目场景:怎么测试这个模块的?测试用例覆盖了哪些场景?

思路实践:

┌─────────────────────────────────────────────────────────────────────────────────┐
│                              测试用例覆盖图                                      │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  1. test_init_deinit        → 初始化和反初始化                                   │
│  2. test_predefined_pool    → 预定义池分配/释放                                  │
│  3. test_pool_full          → 池满处理                                          │
│  4. test_refcount           → 引用计数                                          │
│  5. test_dynamic_pool       → 动态池创建/销毁                                    │
│  6. test_alignment          → 64字节对齐验证                                    │
│  7. test_stats_dump         → 统计信息准确性                                    │
│  8. test_leak_detection     → 内存泄漏检测                                      │
│  9. test_error_handling     → 错误处理(无效指针等)                             │
│ 10. test_stack_macros       → 栈内存宏                                          │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

每个测试都包含:

  • 正常路径:分配、使用、释放

  • 边界条件:池满、空指针、无效参数

  • 异常处理:双重释放、越界访问


八、总结

  1. 简化设计:如果项目不需要共享内存,可以去掉引用计数,简化一半代码

  2. 使用位图管理槽位:替代 slot_used 数组,减少内存占用

  3. 增加池级别统计:方便排查内存问题

  4. 支持编译时配置:通过宏定义选择功能,减少二进制大小

  5. 增加单元测试覆盖率:达到95%以上


九、项目中的经验教训

  1. 内存管理没有银弹:不同的场景需要不同的策略,七字诀是在实践中总结的经验,但不是放之四海而皆准的真理。

  2. 测试驱动设计:复杂的内存管理必须有完善的单元测试,否则改一个问题可能引入三个新问题。

  3. 串行与并发的差异:锁机制是为了未来可能的并行扩展,这是提前设计。

  4. 简单就是美:最终能工作的版本,比一个完美的设计更有价值。不要过度工程化。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐