[ English | 简体中文 ]
内存管理 API
openvela 提供灵活的内存管理系统,支持标准 POSIX 内存分配接口以及扩展的内存管理功能。
头文件:#include <stdlib.h>(标准分配)、#include <nuttx/mm/mm.h>(内核堆/堆管理)
openvela 实现说明
- 构建模式影响:
- Flat Build:只有一个用户堆,
malloc/free直接操作 - Protected Build:内核堆 + 用户堆,通过 MPU 保护隔离
- Kernel Build:内核堆 + 多个用户堆(每个任务组一个)
- Flat Build:只有一个用户堆,
- 对齐保证:
malloc()返回的内存按MM_ALIGN(默认 8 或 16 字节)对齐 - 线程安全:所有标准分配接口(malloc/free/calloc 等)在多任务环境中是线程安全的
- 延迟释放:
*_delayfree()系列接口用于中断上下文中无法立即释放内存的场景 - 已知不兼容:
posix_memalign()当前不检查alignment参数有效性,不返回EINVAL
标准内存分配
malloc
void *malloc(size_t size);
从用户堆中分配指定大小的内存块。malloc() 会在堆中查找一个足够大的空闲块,从中分配所需的内存。如果 size 为 0,行为取决于实现,可能返回 NULL 或返回一个唯一的指针。
分配的内存保证按照 MM_ALIGN(默认为 2 * sizeof(uintptr_t),即 8 或 16 字节)对齐,这确保了对任何基本数据类型的访问都是对齐的。
参数:
size要分配的内存大小(字节)。
返回值:
成功时返回指向分配内存的指针,失败时返回 NULL 并设置 errno:
ENOMEM可用内存不足。
注意:
- 分配的内存内容是未初始化的,可能包含任意数据。
- 返回的指针可以传递给
free()、realloc()等函数。 - 在多任务环境中,
malloc()是线程安全的。
POSIX 兼容性:兼容 POSIX 同名接口。
free
void free(void *ptr);
释放之前通过 malloc()、calloc()、realloc()、memalign() 等分配的内存块,使其可供后续分配使用。
如果 ptr 为 NULL,则不执行任何操作。如果 ptr 不是之前分配函数返回的指针,或者已经被释放过,则行为是未定义的。
参数:
ptr指向要释放的内存块的指针。
返回值:
无返回值。
注意:
- 释放后的指针不应再被使用(悬空指针)。
- 不要重复释放同一块内存(双重释放会导致堆损坏)。
- 不要释放非动态分配的内存(如栈上的变量或全局变量)。
- 释放内存后,该内存可能不会立即返回给系统,而是保留在堆中供后续分配使用。
POSIX 兼容性:兼容 POSIX 同名接口。
calloc
void *calloc(size_t n, size_t elem_size);
分配一个包含 n 个元素的数组,每个元素大小为 elem_size 字节,总共分配 n * elem_size 字节的内存,并将所有字节初始化为零。
与 malloc() 相比,calloc() 有两个优点:它会将内存清零,并且在计算总大小时可以检测乘法溢出(取决于实现)。
参数:
n要分配的元素数量。elem_size每个元素的大小(字节)。
返回值:
成功时返回指向分配并清零的内存的指针,失败时返回 NULL 并设置 errno:
ENOMEM可用内存不足。
注意:
- 如果
n或elem_size为 0,可能返回NULL或返回一个唯一的指针。 - 返回的内存所有字节都被设置为 0。
- 对于需要零初始化的数据结构,推荐使用
calloc()而不是malloc()+memset()。
POSIX 兼容性:兼容 POSIX 同名接口。
realloc
void *realloc(void *ptr, size_t size);
改变之前分配的内存块的大小。realloc() 可能会在原位置扩展或收缩内存块,也可能分配一个新的内存块并复制原有数据。
如果 ptr 为 NULL,则 realloc() 的行为等同于 malloc(size)。如果 size 为 0 且 ptr 不为 NULL,则行为等同于 free(ptr) 并返回 NULL。
参数:
ptr指向之前分配的内存块的指针。如果为NULL,则等同于malloc(size)。size新的内存大小(字节)。如果为 0,则释放内存并返回NULL。
返回值:
成功时返回指向重新分配内存的指针(可能与原指针不同),失败时返回 NULL 并设置 errno:
ENOMEM可用内存不足。此时原内存块保持不变,仍然有效。
注意:
- 如果新大小大于原大小,新增部分的内容是未初始化的。
- 如果新大小小于原大小,超出部分的数据会丢失。
- 返回的指针可能与原指针不同,成功调用后原指针不应再使用。
- 如果
realloc()失败,原内存块不会被释放,调用者仍需负责释放它。
POSIX 兼容性:兼容 POSIX 同名接口。
reallocarray
void *reallocarray(void *ptr, size_t n, size_t elem_size);
改变之前分配的内存块的大小为 n * elem_size 字节。与 realloc() 不同的是,reallocarray() 会安全地检查乘法溢出,防止整数溢出导致的安全问题。
这个函数特别适用于重新分配数组,因为直接使用 realloc(ptr, n * elem_size) 可能会因为乘法溢出而分配一个比预期小得多的内存块。
参数:
ptr指向之前分配的内存块的指针。如果为NULL,则等同于分配新内存。n元素数量。elem_size每个元素的大小(字节)。
返回值:
成功时返回指向重新分配内存的指针,失败时返回 NULL 并设置 errno:
ENOMEM可用内存不足,或者n * elem_size溢出。
注意:
- 如果
n * elem_size会导致整数溢出,函数会安全地返回NULL。 - 与
realloc()相同,失败时原内存块保持不变。
POSIX 兼容性:兼容 BSD/glibc 扩展接口。
zalloc
void *zalloc(size_t size);
分配指定大小的内存块并将所有字节初始化为零。这是 openvela 提供的便捷函数,功能等同于 calloc(1, size),但语义更清晰。
参数:
size要分配的内存大小(字节)。
返回值:
成功时返回指向分配并清零的内存的指针,失败时返回 NULL 并设置 errno:
ENOMEM可用内存不足。
注意:
- 与
malloc()不同,返回的内存已被清零。 - 与
calloc(1, size)功能相同,但调用更简洁。
POSIX 兼容性:openvela 扩展接口。
以下接口用于查询堆的使用情况和内存分配统计信息,对于调试和监控内存使用非常有用。
对齐内存分配
memalign
void *memalign(size_t alignment, size_t size);
分配按指定边界对齐的内存。这对于需要特定对齐要求的硬件访问(如 DMA 缓冲区)或 SIMD 操作非常有用。
参数:
alignment对齐边界,必须是 2 的幂次方(如 16、32、64、4096 等)。size要分配的内存大小(字节)。
返回值:
成功时返回按指定边界对齐的内存指针,失败时返回 NULL 并设置 errno:
ENOMEM可用内存不足。EINVALalignment不是 2 的幂次方。
注意:
- 分配的内存可以使用
free()正常释放。 - 对于需要页对齐的内存,可以使用
valloc()或posix_memalign()。
POSIX 兼容性:兼容 POSIX 同名接口(已过时,推荐使用 posix_memalign())。
posix_memalign
int posix_memalign(void **memptr, size_t alignment, size_t size);
分配按指定边界对齐的内存,并将指针存储在 memptr 中。这是 memalign() 的 POSIX 标准替代接口。
与 memalign() 的主要区别是:posix_memalign() 通过返回值报告错误,而不是设置 errno,这使得错误处理更加明确。
参数:
memptr存储分配内存指针的地址。成功时,*memptr会被设置为分配的内存地址。alignment对齐边界,必须是sizeof(void *)的倍数,且是 2 的幂次方。size要分配的内存大小(字节)。
返回值:
0成功,*memptr指向分配的内存。ENOMEM可用内存不足。
注意:
- 与
memalign()不同,错误通过返回值报告,而不是errno。 - 分配的内存可以使用
free()正常释放。 - openvela 当前实现不检查
alignment参数的有效性,不返回EINVAL(POSIX 标准要求在参数无效时返回EINVAL)。
POSIX 兼容性:部分兼容 POSIX 同名接口(不返回 EINVAL)。
aligned_alloc
void *aligned_alloc(size_t alignment, size_t size);
分配按指定边界对齐的内存。这是 C11 标准引入的对齐内存分配函数。
参数:
alignment对齐边界,必须是 2 的幂次方。size要分配的内存大小(字节)。C11 标准要求size应该是alignment的倍数,但许多实现不强制此要求。
返回值:
成功时返回按指定边界对齐的内存指针,失败时返回 NULL。
注意:
- 分配的内存可以使用
free()正常释放。 - 此函数是 C11 标准的一部分,比
memalign()更具可移植性。
POSIX 兼容性:兼容 C11 标准接口。
valloc
void *valloc(size_t size);
分配按页边界对齐的内存。页大小由系统决定,通常为 4096 字节。
此函数等效于 memalign(sysconf(_SC_PAGESIZE), size)。
参数:
size要分配的内存大小(字节)。
返回值:
成功时返回按页边界对齐的内存指针,失败时返回 NULL。
注意:
- 页大小可以通过
sysconf(_SC_PAGESIZE)获取。 - 分配的内存可以使用
free()正常释放。 - 此函数已过时,新代码应使用
posix_memalign()替代。
POSIX 兼容性:兼容 BSD 扩展接口(已过时,推荐使用 posix_memalign())。
内存信息查询
mallinfo
struct mallinfo mallinfo(void);
获取用户堆的内存分配统计信息。这对于监控应用程序的内存使用情况、检测内存泄漏和优化内存使用非常有用。
参数:
无参数。
返回值:
返回 struct mallinfo 结构体,包含以下字段:
arena堆分配的总内存大小(字节),即堆管理的内存总量。ordblks空闲块的数量。aordblks已分配块的数量。mxordblk最大空闲块的大小(字节),表示单次分配可用的最大内存。uordblks已分配内存的总大小(字节)。fordblks空闲内存的总大小(字节)。usmblks曾经分配的最大内存量(高水位线)。
注意:
uordblks + fordblks应该接近arena(可能略小,因为有堆管理开销)。mxordblk表示当前可以成功分配的最大内存块大小。
POSIX 兼容性:兼容 glibc 扩展接口。
mallinfo_task
struct mallinfo_task mallinfo_task(FAR const struct malltask *task);
获取指定任务或特定类型的内存分配信息。这是 openvela 提供的扩展接口,可以用于追踪每个任务的内存使用情况,帮助定位内存泄漏。
参数:
task指向struct malltask结构体的指针,包含:pid进程 ID。可以是具体的进程 ID,也可以是以下特殊值:PID_MM_MEMPOOL(-1):查询内存池分配。PID_MM_LEAK(-2):查询可能的内存泄漏(分配者已退出)。PID_MM_ALLOC(-3):查询所有已分配的内存。PID_MM_FREE(-4):查询空闲内存。PID_MM_BIGGEST(-5):查询最大内存块。PID_MM_ORPHAN(-6):查询孤立内存块。
seqmin最小序列号(需要配置CONFIG_MM_RECORD_SEQNO)。seqmax最大序列号(需要配置CONFIG_MM_RECORD_SEQNO)。
返回值:
返回 struct mallinfo_task 结构体,包含:
aordblks该任务已分配块的数量。uordblks该任务已分配内存的总大小(字节)。
注意:
- 使用
PID_MM_LEAK可以快速发现已退出任务遗留的内存块,这些很可能是内存泄漏。 - 序列号功能需要启用
CONFIG_MM_RECORD_SEQNO,可以用于追踪特定时间段内的分配。
POSIX 兼容性:openvela 扩展接口。
malloc_size
size_t malloc_size(void *ptr);
获取之前分配的内存块的实际可用大小。由于内存对齐和堆管理的需要,实际分配的内存可能比请求的大小更大。
参数:
ptr指向之前分配的内存块的指针。
返回值:
返回内存块的实际可用大小(字节)。这个值通常大于或等于分配时请求的大小。
注意:
- 也可以使用别名
malloc_usable_size()(与 glibc 兼容)。 - 可以安全地使用返回值范围内的所有内存。
- 如果
ptr不是有效的分配指针,行为是未定义的。
POSIX 兼容性:兼容 glibc/macOS 扩展接口。
mallopt
int mallopt(int param, int value);
调整内存分配器的参数。此函数提供了一种控制内存分配器行为的方式。
参数:
param要调整的参数,定义的选项包括:M_TRIM_THRESHOLD收缩阈值M_TOP_PAD顶部填充M_MMAP_THRESHOLDmmap 阈值M_MMAP_MAX最大 mmap 数量M_CHECK_ACTION检查动作M_PERTURB内存扰动M_ARENA_TESTarena 测试M_ARENA_MAX最大 arena 数量
value参数值。
返回值:
成功返回非零值,失败返回 0。
注意:
- openvela 当前实现总是返回 1(成功),不实际处理任何参数。
- 此接口仅为兼容性目的提供。
POSIX 兼容性:兼容 glibc 扩展接口(仅接口兼容,无实际功能)。
内核堆接口
kmm_initialize
void kmm_initialize(void *heap_start, size_t heap_size);
初始化内核堆。此函数通常在系统启动早期由板级初始化代码调用。
参数:
heap_start内核堆内存的起始地址。heap_size内核堆的大小(字节)。
返回值:
无返回值。
注意:
- 此函数只应调用一次,重复调用会导致未定义行为。
- 需要启用
CONFIG_MM_KERNEL_HEAP配置。
kmm_malloc
void *kmm_malloc(size_t size);
从内核堆分配内存。功能与 malloc() 相同,但从内核堆而非用户堆分配。
参数:
size要分配的内存大小(字节)。
返回值:
成功时返回指向分配内存的指针,失败时返回 NULL。
注意:
- 分配的内存只能使用
kmm_free()释放。 - 内核堆分配的内存不应传递给用户态代码。
kmm_free
void kmm_free(void *mem);
释放之前通过 kmm_malloc()、kmm_calloc() 等从内核堆分配的内存。
参数:
mem指向要释放的内存块的指针。如果为NULL,则不执行任何操作。
返回值:
无返回值。
注意:
- 只能释放内核堆分配的内存,不能用于释放用户堆内存。
- 可以使用
kmm_heapmember()检查指针是否属于内核堆。
kmm_calloc
void *kmm_calloc(size_t n, size_t elem_size);
从内核堆分配内存并清零。功能与 calloc() 相同,但从内核堆分配。
参数:
n要分配的元素数量。elem_size每个元素的大小(字节)。
返回值:
成功时返回指向分配并清零的内存的指针,失败时返回 NULL。
kmm_realloc
void *kmm_realloc(void *oldmem, size_t newsize);
重新分配内核堆内存。功能与 realloc() 相同,但在内核堆上操作。
参数:
oldmem指向之前从内核堆分配的内存块的指针。如果为NULL,则等同于kmm_malloc(newsize)。newsize新的内存大小(字节)。如果为 0,则释放内存。
返回值:
成功时返回指向重新分配内存的指针(可能与原指针不同),失败时返回 NULL(原内存块保持不变)。
kmm_zalloc
void *kmm_zalloc(size_t size);
从内核堆分配内存并清零。功能与 zalloc() 相同,但从内核堆分配。
参数:
size要分配的内存大小(字节)。
返回值:
成功时返回指向分配并清零的内存的指针,失败时返回 NULL。
kmm_memalign
void *kmm_memalign(size_t alignment, size_t size);
从内核堆分配对齐内存。功能与 memalign() 相同,但从内核堆分配。
参数:
alignment对齐边界,必须是 2 的幂次方。size要分配的内存大小(字节)。
返回值:
成功时返回按指定边界对齐的内存指针,失败时返回 NULL。
注意:
- 用于内核需要对齐内存的场景,如 DMA 缓冲区。
kmm_malloc_size
size_t kmm_malloc_size(void *mem);
获取内核堆中已分配内存块的实际可用大小。
参数:
mem指向内核堆中已分配的内存块。
返回值:
返回内存块的实际可用大小(字节)。
POSIX 兼容性:openvela/NuttX 扩展接口。
kmm_mallinfo
struct mallinfo kmm_mallinfo(void);
获取内核堆的分配信息。功能与 mallinfo() 相同,但返回内核堆的统计信息。
参数:
无参数。
返回值:
返回 struct mallinfo 结构体,包含内核堆的内存分配统计信息:
arena内核堆的总大小(字节)。ordblks空闲块的数量。uordblks已使用的内存大小(字节)。fordblks空闲内存大小(字节)。mxordblk最大连续空闲块大小(字节)。
注意:
- 可用于监控内核内存使用情况。
kmm_heapmember
bool kmm_heapmember(void *mem);
检查内存地址是否属于内核堆。
参数:
mem要检查的内存地址。
返回值:
如果内存地址属于内核堆,返回 true;否则返回 false。
注意:
- 可用于确定内存块应该使用
kmm_free()还是free()释放。 - 在内存管理代码中用于路由释放请求到正确的堆。
kmm_addregion
void kmm_addregion(void *heapstart, size_t heapsize);
向内核堆添加一个新的内存区域。允许内核堆使用非连续的内存区域。
参数:
heapstart新内存区域的起始地址。heapsize新内存区域的大小(字节)。
返回值:
无返回值。
注意:
- 需要启用
CONFIG_MM_KERNEL_HEAP。 - 最大区域数量由
CONFIG_MM_REGIONS配置。
POSIX 兼容性:openvela/NuttX 扩展接口。
kmm_extend
void kmm_extend(void *mem, size_t size, int region);
扩展内核堆的指定内存区域。新增内存必须与现有区域在物理地址上相邻。
参数:
mem新增内存的起始地址。size新增内存的大小(字节)。region区域索引(从 0 开始)。
返回值:
无返回值。
POSIX 兼容性:openvela/NuttX 扩展接口。
kmm_delayfree
void kmm_delayfree(void *mem);
延迟释放内核堆内存。将释放操作推迟到安全的时机执行,适用于中断上下文或持有自旋锁时无法立即释放内存的场景。
参数:
mem指向要释放的内核堆内存。
返回值:
无返回值。
注意:
- 在中断处理程序中释放内存时应使用此函数,而非
kmm_free()。
POSIX 兼容性:openvela/NuttX 扩展接口。
kmm_memdump
void kmm_memdump(const struct mm_memdump_s *dump);
转储内核堆的内存分配信息到系统日志,用于调试内存泄漏。
参数:
dump指向转储条件结构体,指定过滤条件(PID、序列号范围等)。
返回值:
无返回值。
注意:
- 需要启用
CONFIG_MM_BACKTRACE以获取分配调用栈信息。
POSIX 兼容性:openvela/NuttX 扩展接口。
kmm_checkcorruption
void kmm_checkcorruption(void);
检查内核堆是否存在内存损坏。
参数:
无参数。
返回值:
无返回值。如果检测到内存损坏,将触发断言或输出调试信息。
注意:
- 需要启用
CONFIG_MM_HEAP_CHECK配置。 - 用于调试内存相关问题。
堆管理接口
mm_initialize
struct mm_heap_s *mm_initialize(const char *name, void *heapstart, size_t heapsize);
初始化一个新的堆。分配并初始化堆管理结构,设置初始空闲块。
参数:
name堆的名称,用于调试和识别。heapstart堆内存的起始地址。heapsize堆的大小(字节)。
返回值:
成功时返回指向初始化的堆结构的指针,失败时返回 NULL。
注意:
- 堆大小必须足够大以容纳堆管理开销。
- 系统可以有多个独立的堆,如用户堆、内核堆、图形堆等。
mm_uninitialize
void mm_uninitialize(struct mm_heap_s *heap);
销毁一个堆,释放堆管理结构占用的资源。
参数:
heap要销毁的堆结构指针。
返回值:
无返回值。
注意:
- 销毁前应确保堆中没有活动的分配。
mm_addregion
void mm_addregion(struct mm_heap_s *heap, void *heapstart, size_t heapsize);
向现有堆添加一个新的内存区域。这允许堆使用非连续的内存区域。
参数:
heap堆结构指针。heapstart新内存区域的起始地址。heapsize新内存区域的大小(字节)。
返回值:
无返回值。
注意:
- 新增区域可以在物理上与已有区域不连续。
- 最大区域数量由
CONFIG_MM_REGIONS配置。
mm_extend
void mm_extend(struct mm_heap_s *heap, void *mem, size_t size, int region);
扩展堆的指定内存区域。新增内存必须与现有区域相邻。
参数:
heap堆结构指针。mem新增内存区域的起始地址。size新增内存区域的大小(字节)。region区域索引(从 0 开始)。
返回值:
无返回值。
注意:
- 新增的内存区域必须与现有区域在物理地址上相邻。
- 与
mm_addregion()不同,此函数用于扩展已有区域而非添加新区域。
mm_brkaddr
void *mm_brkaddr(struct mm_heap_s *heap, int region);
获取堆指定区域的当前 break 地址(区域末尾地址)。
参数:
heap堆结构指针。region区域索引(从 0 开始)。
返回值:
返回指定区域的当前 break 地址。
注意:
- 用于确定可以扩展的内存位置。
mm_sbrk
int mm_sbrk(struct mm_heap_s *heap, intptr_t incr, void **mem);
扩展或收缩堆的 break 地址(类似 UNIX sbrk 语义)。
参数:
heap堆结构指针。incr增量(正值扩展,负值收缩)。mem输出参数,返回之前的 break 地址。
返回值:
成功返回 0,失败返回 -1。
POSIX 兼容性:openvela/NuttX 扩展接口。
mm_heapmember
bool mm_heapmember(struct mm_heap_s *heap, void *mem);
检查内存地址是否属于指定堆的任意区域。
参数:
heap堆结构指针。mem要检查的内存地址。
返回值:
如果内存地址属于指定堆,返回 true;否则返回 false。
注意:
- 用于确定内存分配来源,以便使用正确的接口释放。
mm_free
void mm_free(struct mm_heap_s *heap, void *mem);
从指定堆释放内存。这是底层堆释放接口,free() 和 kmm_free() 内部调用此函数。
参数:
heap堆结构指针。mem指向要释放的内存块。
返回值:
无返回值。
POSIX 兼容性:openvela/NuttX 扩展接口。
mm_malloc_size
size_t mm_malloc_size(struct mm_heap_s *heap, void *mem);
获取指定堆中已分配内存块的实际可用大小。
参数:
heap堆结构指针。mem指向已分配的内存块。
返回值:
返回内存块的实际可用大小(字节)。
POSIX 兼容性:openvela/NuttX 扩展接口。
mm_delayfree
void mm_delayfree(struct mm_heap_s *heap, void *mem);
延迟释放指定堆的内存。适用于中断上下文或持有自旋锁时无法立即释放的场景。
参数:
heap堆结构指针。mem指向要释放的内存块。
返回值:
无返回值。
POSIX 兼容性:openvela/NuttX 扩展接口。
mm_heapfree
size_t mm_heapfree(struct mm_heap_s *heap);
查询指定堆的空闲内存总量。
参数:
heap堆结构指针。
返回值:
返回堆中空闲内存的总大小(字节)。
POSIX 兼容性:openvela/NuttX 扩展接口。
mm_heapfree_largest
size_t mm_heapfree_largest(struct mm_heap_s *heap);
查询指定堆中最大的连续空闲块大小。这决定了单次分配可用的最大内存。
参数:
heap堆结构指针。
返回值:
返回最大连续空闲块的大小(字节)。
POSIX 兼容性:openvela/NuttX 扩展接口。
mm_notify_pressure
void mm_notify_pressure(size_t remaining, size_t largest);
发送内存压力通知。当堆空闲内存低于阈值时,通知注册的监听者释放缓存等可回收内存。
参数:
remaining当前剩余空闲内存(字节)。largest当前最大连续空闲块(字节)。
返回值:
无返回值。
POSIX 兼容性:openvela/NuttX 扩展接口。
用户堆接口
umm_initialize
void umm_initialize(void *heap_start, size_t heap_size);
初始化用户堆。此函数通常在系统启动时由初始化代码调用。
参数:
heap_start堆内存的起始地址。heap_size堆的大小(字节)。
返回值:
无返回值。
注意:
- 此函数只应调用一次。
- 用户堆是
malloc()等标准接口的默认堆。
umm_heapmember
bool umm_heapmember(void *mem);
检查内存地址是否属于用户堆。
参数:
mem要检查的内存地址。
返回值:
如果内存地址属于用户堆,返回 true;否则返回 false。
注意:
- 与
kmm_heapmember()配合使用,可以确定内存来源。
umm_addregion
void umm_addregion(void *heapstart, size_t heapsize);
向用户堆添加一个新的内存区域。
参数:
heapstart新内存区域的起始地址。heapsize新内存区域的大小(字节)。
返回值:
无返回值。
POSIX 兼容性:openvela/NuttX 扩展接口。
umm_extend
void umm_extend(void *mem, size_t size, int region);
扩展用户堆的指定内存区域。新增内存必须与现有区域相邻。
参数:
mem新增内存的起始地址。size新增内存的大小(字节)。region区域索引。
返回值:
无返回值。
POSIX 兼容性:openvela/NuttX 扩展接口。
umm_delayfree
void umm_delayfree(void *mem);
延迟释放用户堆内存。适用于中断上下文。
参数:
mem指向要释放的用户堆内存。
返回值:
无返回值。
POSIX 兼容性:openvela/NuttX 扩展接口。
调试与诊断
mm_memdump
void mm_memdump(struct mm_heap_s *heap, const struct mm_memdump_s *dump);
转储堆的内存分配信息,用于调试内存泄漏和分析内存使用情况。
参数:
heap堆结构指针。如果为NULL,则转储用户堆。dump指向struct mm_memdump_s结构体的指针,用于指定转储条件。
返回值:
无返回值。
注意:
mm_memdump_s是malltask的类型别名,结构体字段与mallinfo_task()中描述的malltask相同。- 输出信息包括每个分配块的地址、大小、分配者 PID 和分配时的调用栈(如果启用了
CONFIG_MM_BACKTRACE)。 - 常用于诊断内存泄漏,找出哪些代码分配了内存但未释放。
mm_checkcorruption
void mm_checkcorruption(struct mm_heap_s *heap);
检查堆是否存在内存损坏。此函数遍历堆中所有内存块,验证其完整性。
参数:
heap要检查的堆结构指针。
返回值:
无返回值。如果检测到内存损坏,将触发断言或输出调试信息。
注意:
- 需要启用
CONFIG_DEBUG_MM配置。 - 检测的问题包括:块头损坏、双重释放、越界写入等。
- 此函数会遍历整个堆,对性能有影响,主要用于调试。
umm_checkcorruption
void umm_checkcorruption(void);
检查用户堆是否存在内存损坏。这是 mm_checkcorruption() 对用户堆的便捷包装。
参数:
无参数。
返回值:
无返回值。如果检测到内存损坏,将触发断言或输出调试信息。
注意:
- 需要启用
CONFIG_DEBUG_MM配置。 - 可以在怀疑有内存问题时调用此函数进行检查。
umm_memdump
void umm_memdump(const struct mm_memdump_s *dump);
转储用户堆的内存分配信息到系统日志。
参数:
dump指向转储条件结构体。
返回值:
无返回值。
注意:
- 需要启用
CONFIG_MM_BACKTRACE以获取调用栈。
POSIX 兼容性:openvela/NuttX 扩展接口。