CoreDump_2021-05-26_14-40-18
dump log 显示是访问了非法内存地址
Memory Management fault: Data access violation @0x10000a0d
trace 32 解析dump
死机时执行的汇编代码
str r0,[r3] ; pxBlockToInsert,[r3]
查看R3寄存器为 10000A0D
确实访问了内存地址 0x10000A0D
再看调用栈情况
死机位置
prvInsertBlockIntoFreeList
prvInsertBlockIntoFreeList 函数里面,在迭代寻找插入freeblock的位置,访问了0x10000A0D。
!
而0x10000A0D并不是合法的一个8字节对齐的地址, 0x10000A0D & 0x07 = 5,所以会死机。
0x10000A0D 是怎么来的?
pdata = 0x10092C90 的block大小是0x408, 减去header大小8也就是1024字节
dump 0x10092C90 + 1024的内存数据,\r\n 正好是0x0D,0x0A,内存被踩。
1056 字节的数据是怎么来的?
变量 apb_proxy_event_t apb_proxy_event; 未赋值初始化,可能会有问题。
1024 + 32 = 1056
所以死机根本原因是 0x10092C90 这段内存,写超了1024个字节导致。
CoreDump_2021-05-28_10-36-39
死机log
对应代码,malloc 是,内存block划分得到的地址没有8字节对齐,触发了assert。
也是内存被破坏的问题。
0x000A0D34 怎么来的?
A*34\r\n 正好是0A 0D 34,猜测也是内存overwrite问题。
CoreDump_2021-05-28_10-51-25
死机log
也是内存被踩问题。
分析总结
- 检查访问的地址是否字节对齐,BC20平台的动态申请内存地址是按8字节对齐的,内存地址&0x07要等于0。
- 检查全局变量空闲内存列表xStart是否有非法内存地址,地址在不在heap地址范围,链表记录的block地址是否都是字节对齐的。
- 检查malloc返回的某个地址是否写穿,可以对该 (内存地址-0x8) 解析为 BlockLint_t * 结构体(head 大小占用8字节),查看这块内存分配的block大小,然后dump这段内存的结束地址,看下一个链表节点纪录的数据是否正常的,有没有被破坏。
- BC20平台使用的os是freertos, heap 内存分配策略是first fit方式,且从dump看,内存块的数据结构BlockLint_t 没有记录caller地址。