arm 结构体对齐的诡谲BUG,求解释
arm 结构体对齐的诡异BUG,求解释
楼主在arm平台下遇到一个问题。 在给以1字节对齐的结构体,在给其成员赋值时,竟然出现诡异现象。
1、 结构体原型, 以1字节对齐
2、 出错函数调用
3、 错误函数内部处理
4、 错误现象
我调用Funccall时传入的是ui16NewStreamId的地址,结果却将修改了ui16OldStreamId的高位字节和 ui16NewStreamId的低位字节。
5、 汇编跟踪
上述步骤5中标注@@@@@@的汇编代码中, 我明明是将0x4448赋值到3地址,结果却是
2地址的值为: 48
3地址的值为: 44
而我的期望应该是
2地址的值不变
3:地址的值为: 48
4地址的值为: 44
而我将出错函数中的形式修改为
g_streamIndentify. ui16NewStreamId = 0x4448;确能正确修改这个值。
这BUG从何而来,本人不熟悉arm汇编指令。 故求解。
------解决方案--------------------
某些平台是不支持 不对齐数据的操作的。
改用位操作赋值吧。
------解决方案--------------------
比如ARM
------解决方案--------------------
这运气不错了, 我遇到的没对齐的时候一般程序就跑飞了 ...
------解决方案--------------------
果然如此。
Taking the address of a field in a #pragma packed struct does not yield a __packed pointer, so the compiler does not produce an error if you assign this address to a non-__packed pointer. However, the field might not be properly aligned for its type, and dereferencing such an unaligned pointer results in undefined behavior.
楼主在arm平台下遇到一个问题。 在给以1字节对齐的结构体,在给其成员赋值时,竟然出现诡异现象。
1、 结构体原型, 以1字节对齐
#pragma pack(push, 1)
typedef struct AAAA
{
Uint8 ui8StreamIndex;
Uint16 ui16OldStreamId;
Uint16 ui16NewStreamId;
}
#pragma pack(pop)
2、 出错函数调用
// cpp中全局变量
AAAA g_streamIndentify;
//出错函数声明
int Funccall(......, Uint16 *pStreamID, ...);
// 过程中调用参数时传入地址
Funccall(..., &g_streamIndentify.ui16NewStreamId,...);
3、 错误函数内部处理
int Funccall(......, Uint16 *pStreamID, ...);
{
//......
*pStreamID = 0x4448;
}
4、 错误现象
我调用Funccall时传入的是ui16NewStreamId的地址,结果却将修改了ui16OldStreamId的高位字节和 ui16NewStreamId的低位字节。
5、 汇编跟踪
int Funccall(......, Uint16 *pStreamID, ...);
{
//......
*pStreamID = 0x4448 // g_streamIndentify的地址假设是0,依次类推
// ui8StreamIndex的地址是0; 占用内存地址0
// ui16OldStreamId的地址是1;占用内存区域是1、2
// ui16NewStreamId的地址是3; 占用内存区域是3、4
ldr r3, [r11, #-44] // 该句话是将pstreamID保存的地址赋值到 r3寄存器,
// 完成后, r3寄存器的值为3(同上述假设)
ldr r2, 0x4448h ; 我翻译后的代码,原文应该类似于 ldr r2, [pc, #****];
strh r2, [r3] // 将4448h, 赋值到虚拟内存为3的位置。 @@@@@@]
}
上述步骤5中标注@@@@@@的汇编代码中, 我明明是将0x4448赋值到3地址,结果却是
2地址的值为: 48
3地址的值为: 44
而我的期望应该是
2地址的值不变
3:地址的值为: 48
4地址的值为: 44
而我将出错函数中的形式修改为
g_streamIndentify. ui16NewStreamId = 0x4448;确能正确修改这个值。
这BUG从何而来,本人不熟悉arm汇编指令。 故求解。
------解决方案--------------------
某些平台是不支持 不对齐数据的操作的。
改用位操作赋值吧。
------解决方案--------------------
比如ARM
------解决方案--------------------
这运气不错了, 我遇到的没对齐的时候一般程序就跑飞了 ...
------解决方案--------------------
果然如此。
Taking the address of a field in a #pragma packed struct does not yield a __packed pointer, so the compiler does not produce an error if you assign this address to a non-__packed pointer. However, the field might not be properly aligned for its type, and dereferencing such an unaligned pointer results in undefined behavior.