Liteos中查看内存分配的调用栈

在liteos中内存分配主要是los_memory.c提供的相关方法,当设备内存有限时,内存资源紧张,需要对系统中申请内存的位置进行分析,可通过下面的步骤进行

1. 在函数开头获取调用者地址

由于嵌入式环境通常不支持完整的 backtrace(),可采用 GCC 内建函数 __builtin_return_address(n) 获取直接调用者(最常用)或上层调用者。

STATIC INLINE VOID *OsMemAlloc(struct OsMemPoolHead *pool, UINT32 size, UINT32 intSave)
{
    // >>> 新增:获取直接调用者地址(即谁调用了 OsMemAlloc)
    UINTPTR caller = (UINTPTR)__builtin_return_address(0);
    // <<<
}

说明:

  • __builtin_return_address(0) 返回 直接调用者 的返回地址(即 OsMemAlloc 被调用后要返回的位置);
  • 在 ARM Cortex-M 等架构下,这通常是调用指令(如 BL)的下一条指令地址;
  • 需确保编译器未优化掉帧指针(建议调试时使用 -O0 或 -fno-omit-frame-pointer)。

2. 在分配成功后打印带 caller 的日志

STATIC INLINE VOID *OsMemAlloc(struct OsMemPoolHead *pool, UINT32 size, UINT32 intSave)
{
    // >>> 新增:获取直接调用者地址(即谁调用了 OsMemAlloc)
    UINTPTR caller = (UINTPTR)__builtin_return_address(0);
    // <<<
    
  // 内存分配等操作

    // >>> 新增:打印带 caller 的日志
    PRINTK("0xc00 OsMemAlloc  Caller: 0x%lx\n", (unsigned long)caller);
    // <<<
}

输出日志如下:

0xc00 OsMemAlloc  Caller: 0x0800c3a2

提示:

  • 使用 0x%lx 打印 UINTPTR 类型(兼容 32/64 位);
  • 日志前缀 0xc00 可保留,便于过滤。

将Caller地址转为函数名和位置

使用交叉编译工具链中的 addr2line和变异产物中的.elf文件

shell>riscv-none-embed-addr2line.exe -e LiteOS_m.elf -f -C 0xbd4c
OsQueueCreate
xxx/../kernel_liteos_m/kernel/src/los_queue.c:171

__builtin_return_address可传入其他的数字,表示获取更上层调用者,但可靠性随 n 增大急剧下降。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐