当前位置: 首页 > news >正文

也来混rt_thread了,碰到一个内存释放问题,顺便聊聊思路

刚入行单片机开发,赶鸭子上架,简单开聊,纯粹是做一个记录,

总体来说,问题本身比较低端,但是在缺乏调试手段(Keil的没有),不熟悉代码,碰到这种问题还真不是一时半会可以搞定。

简单描述,串口上看到单板启动后,出现如下错误。

free memory: memory[0x60001470], block[0x60001458] 
((header_ptr->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC) assertion failed at function:rt_memheap_free, line number:515

一个典型的内存释放时,发现魔术字不对的问题。

由于地址看起来正常,野指针访问的可能性有点大

0x60000000开口的512K,实际就是外部RAM,当前单片机STM32F407,自带128K RAM

#define STM32_SRAM_SIZE           128

#define STM32_SRAM_END            (0x20000000 + STM32_SRAM_SIZE * 1024)

设计上,增加了512K 外设RAM

#define STM32_ESRAM_START          0x60000000

#define STM32_ESRAM_SIZE           512

#define STM32_ESRAM_END            (0x60000000 + STM32_ESRAM_SIZE * 1024)

想要得到足够的信息,还得打开日志开关,

#ifndef RT_DEBUG_MEMHEAP

#define RT_DEBUG_MEMHEAP               1

#endif

于是差不多有刷屏的打印,好在问题出在单板初始化阶段,眼里尚能抵达。

allocate 72 on heap:heapSRAMsplit: block[0x60001454] nextm[0x6007ffe8] prevm[0x6000142c] to new[0x600014b4]
new ptr: next_free 0x20009568, prev_free 0x20009568
alloc mem: memory[0x6000146c], heap[0x60001454], size: 72 -->这里0x6000146c - 0x60001454 = 24 字节,就是内存管理头大小。
free memory: memory[0x60001358], block[0x60001340]

/**
 * memory item on the heap
 */
struct rt_memheap_item
{
    rt_uint32_t             magic;                      /**< magic number for memheap */
    struct rt_memheap      *pool_ptr;                   /**< point of pool */

    struct rt_memheap_item *next;                       /**< next memheap item */
    struct rt_memheap_item *prev;                       /**< prev memheap item */

    struct rt_memheap_item *next_free;                  /**< next free memheap item */
    struct rt_memheap_item *prev_free;                  /**< prev free memheap item */
};

跟踪alloc+free的配对流程,对照assert前的地址,差不多能够确定可疑点。

merge: right node 0x600013d4, next_free 0x600014b4, prev_free 0x20009568
insert to free list: next_free 0x600014b4, prev_free 0x20009568
free memory: memory[0x60001470], block[0x60001458] --> 实际上应该是0x60001454,指针偏移了4字节。
((header_ptr->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC) assertion failed at function:rt_memheap_free, line number:515
 

笔者想偷懒,结果没有成功,方法是替换assert,代码替换为除零错误,来激发cmbacktrace,这样就可以拿到调用栈,可惜总是不成功,刚入行,还不知道多少坑要填。

最后老老实实走读代码,非常费眼神,有调试器的话,其实就分分钟的事。

碰到的问题,其实不仅仅如此,初始化过程中还存在着一个小内存操作,从片外拷贝到片内,然后crash了,代码走读看起来没有问题,尚不知道原因。

规避方法为,对于该模块内部,所有的内存申请和释放,用8字节对齐方式。

void cJSON_free(void *ptr)
{
	/* free a RT_NULL pointer */
    if (ptr == RT_NULL)
        return ;

    rt_free_align(ptr);
}
void* cJSON_malloc(rt_size_t size)
{
   return rt_malloc_align(size, 8);
}

相关文章:

  • 高阶SQL语句(二)
  • 电脑WinSxS文件夹太大,如何清理?分享四种方法
  • 【循环神经网络rnn】一篇文章讲透
  • C++入门:类和对象(上)
  • 【boost_search搜索引擎】2.正排索引和倒排索引
  • 37、Linux中Xsync数据同步备份工具
  • [BT]BUUCTF刷题第9天(3.27)
  • Golang-web开发好用的依赖库
  • 苹果与百度合作,将在iPhone 16中使用生成式AI
  • DSP 看门狗权威解读
  • pytorch常用的模块函数汇总(2)
  • stm32使用定时器实现PWM与呼吸灯
  • 备考ICA----Istio实验9---熔断Circuit Breaking 实验
  • 第一篇:概述、 目录、适用范围及术语 --- IAB/MRC《增强现实(AR)广告(效果)测量指南1.0 》
  • 主流的开发语言、环境及其特点
  • 【深度学习】【机器学习】用神经网络进行入侵检测,NSL-KDD数据集,基于机器学习(深度学习)判断网络入侵
  • 前端学习<二>CSS基础——04-CSS选择器:伪类
  • QT 常用模块介绍以及使用说明
  • YOLOv9改进策略:IoU优化 | Wasserstein Distance Loss,助力小目标涨点
  • java中的static和单例模式
  • https://app.hackthebox.com/machines/Inject
  • Spring —— Spring简单的读取和存储对象 Ⅱ
  • 渗透测试之冰蝎实战
  • Mybatis、TKMybatis对比
  • Microsoft Office 2019(2022年10月批量许可版)图文教程
  • 《谷粒商城基础篇》分布式基础环境搭建
  • 哈希表题目:砖墙
  • Vue 3.0 选项 生命周期钩子
  • 【车载嵌入式开发】AutoSar架构入门介绍篇
  • 【计算机视觉 | 目标检测】DETR风格的目标检测框架解读