目录
- 前言
- 背景代码
- 直接运行的现象
- 问题原因
- 解决办法
前言
1,memcpy在keil中是伪装成函数的C语言关键字,有可能会被优化为字对齐形式__rt_memcpy_w
2,编译到memcpy位置的时候,编译器会检查地址类型,如果两个指针都是4字节对齐的,那么就调用__rt_memcpy_w
3,向__rt_memcpy_w传入非对其的地址会触发hardfault
背景代码
typedef struct MBX_STRUCT_PACKED_START
{UINT16 Length; /**< \brief Length*/UINT16 Address; /**< \brief Address*/UINT16 Flags[1]; /**< \brief Flags*/
}MBX_STRUCT_PACKED_END
TMBXHEADER;typedef struct MBX_STRUCT_PACKED_START
{TMBXHEADER MbxHeader; /**< \brief Mailbox header*/UINT16 Data[(MAX_MBX_DATA_SIZE >> 1)]; /**< \brief Mailbox data*/
}MBX_STRUCT_PACKED_END
TMBX;UINT16 AmsFragRes(AmsCmd *pCmd, UINT16 dataLen)
{AmsCmd *pFragCmd;pMbx = (TMBX *) malloc(size + SIZEOF(AmsHead) + MBX_HEADER_SIZE);pFragCmd = (AmsCmd *) pMbx->Data;memcpy(pFragCmd, pCmd, dataLen + SIZEOF(AmsHead));
}
直接运行的现象
问题原因
memcpy的目的地址pMbx->Data原本是一个16位数组,pFragCmd 指向数组首地址,pFragCmd 被强制转换为(AmsCmd *)形式之后,编译器认为这个地址是四字节对齐的,所以调用了__rt_memcpy_w
解决办法
1, 结构体类型定义的时候告诉编译器__packed,(请仅在数据包场景使用这个办法,这会导致结构体访问效率降低)
2,传入memcpy的指针强制转换为uint8_t *,直接禁用优化
3,传入memcpy的指针强制转换为void *,编译器会{智能}识别地址类型