rtthread 字节对齐问题 int指针访问非对齐地址崩溃
环境:
SOC: i.MX RT1050
底板: 野火 RT1052
Kernel: rt-thread
背景:
我正在实现解析udp包, 而udp包的结构不是字节对齐的, 这个时候我使用__packed来说明按照1字节对齐, 在解析udp包数据的地方, 取udp->srcaddr这个成员的值的时候, 出现 UNALIGN(未对齐) 错误. 我将该问题用以下代码来复现. 如果有更好的网络协议数据结构体定义方式, 还请告知, 谢谢
现象:
使用rtthread master版 生成的工程运行后会出现以下问题, 但使用裸机程序, 或者 rtthread nano版 运行后不会出现以下问题. 这个问题还未有答案, 如果有哪位道友, 遇到了, 一起学习探讨
/*
1.内存 堆区
a.uint32_t* 类型, 所指向的地址必须是四字节对齐
b.uint16_t* 类型, 所指向的地址必须是两字节对齐
2.内存 RW/ZI 区
a.uint32_t* 类型, 所指向的地址必须是四字节对齐
b.uint16_t* 类型, 所指向的地址必须是两字节对齐
3.DTCM
a.uint32_t* 类型, 非四字节对齐地址任然可以访问
b.uint16_t* 类型, 非两字节对齐地址任然可以访问
4.内存 栈区
定义一字节对齐结构体, 任意成员可以访问
5.内存 栈区 char数组
a.uint32_t* 类型, 非四字节对齐地址无法访问
a.uint16_t* 类型, 非两字节对齐地址无法访问
*/
/* 内存 栈区 char数组
__packed char data[128];
rt_kprintf("&data[0]: %p\n", &data[0]);
__packed uint32_t* p = (__packed uint32_t*)(&data[0]);
rt_kprintf("*p: %x\n", *p);
p = (__packed uint32_t*)(&data[0]+1);
rt_kprintf("p: %p\n", p);
rt_kprintf("*p: %x\n", *p);
__packed uint16_t* p2 = (__packed uint16_t*)(data);
rt_kprintf("*p2: %x\n", *p2);
p2 = (__packed uint16_t*)(data+1);
rt_kprintf("*p2: %x\n", *p2);
p2 = (__packed uint16_t*)(data+3);
rt_kprintf("*p2: %x\n", *p2);*/
rt_kprintf("sizeof(eth_hdr): %d; sizeof(ip_hdr): %d\n",sizeof(eth_hdr),sizeof(ip_hdr));
uint8_t* tpoint = (uint8_t*)malloc(60);
rt_kprintf("tpoint: %p\n", tpoint);
eth_hdr* ethhdr = (eth_hdr*)tpoint;
tpoint += sizeof(eth_hdr);
ip_hdr* iphdr = (ip_hdr*)tpoint;
rt_kprintf("tpoint: %p\n", tpoint);
rt_kprintf("iphdr: %p\n", iphdr);
iphdr->tlen = 0x10;
rt_kprintf("iphdr->tlen: %x\n", iphdr->tlen);
rt_kprintf("&iphdr->srcaddr: %p\n", &iphdr->srcaddr);
iphdr->srcaddr = 0x1111;
rt_kprintf("iphdr->srcaddr: %x\n", iphdr->srcaddr);
/* 内存 栈区 一字节对齐结构体访问
ip_hdr iphdr;
iphdr.srcaddr = 0x1111;
rt_kprintf("sizeof(iphdr): %d\n", sizeof(iphdr));
rt_kprintf("iphdr.srcaddr: %d\n", iphdr.srcaddr);*/
/* DTCM 0x20000000
uint32_t* p = (uint32_t*)0x20000000;
rt_kprintf("*p: %x\n", *p);
p = (uint32_t*)0x20000004;
rt_kprintf("*p: %x\n", *p);
p = (uint32_t*)0x20000008;
rt_kprintf("*p: %x\n", *p);
uint16_t* p2 = (uint16_t*)0x20000000;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x20000002;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x20000004;
rt_kprintf("*p2: %x\n", *p2);
p = (uint32_t*)0x20000001;
rt_kprintf("*p: %x\n", *p);
p2 = (uint16_t*)0x20000001;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x20000003;
rt_kprintf("*p2: %x\n", *p2);*/
/* 内存 RW/ZI 区, 字节对齐测试
uint32_t* p = (uint32_t*)0x80200000;
rt_kprintf("*p: %x\n", *p);
p = (uint32_t*)0x80200004;
rt_kprintf("*p: %x\n", *p);
p = (uint32_t*)0x80200008;
rt_kprintf("*p: %x\n", *p);
uint16_t* p2 = (uint16_t*)0x80200000;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x80200002;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x80200004;
rt_kprintf("*p2: %x\n", *p2);
p = (uint32_t*)0x80200001;
rt_kprintf("*p: %x\n", *p);
p2 = (uint16_t*)0x80200001;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x80200003;
rt_kprintf("*p2: %x\n", *p2);*/
/* 堆区, 字节对齐测试
uint32_t* p = (uint32_t*)0x802059a0;
rt_kprintf("*p: %x\n", *p);
p = (uint32_t*)0x802059a4;
rt_kprintf("*p: %x\n", *p);
p = (uint32_t*)0x802059a8;
rt_kprintf("*p: %x\n", *p);
uint16_t* p2 = (uint16_t*)0x802059a0;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x802059a2;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x802059a4;
rt_kprintf("*p2: %x\n", *p2);
p = (uint32_t*)0x802059a1;
rt_kprintf("*p: %x\n", *p);
p2 = (uint16_t*)0x802059a1;
rt_kprintf("*p2: %x\n", *p2);
p2 = (uint16_t*)0x802059a3;
rt_kprintf("*p2: %x\n", *p2);*/
程序崩溃报错图示:
在 rtthread nano版 中执行 “内存 RW/ZI 区” 测试, 测试结果如下