今天遇到一个问题,调试了一天.
大致描述一下,移植一个开源项目的代码,原来在mips平台上运行正常,后来到arm平台的机器上运行,结果运行时出错了.
一般的,这样的问题,脑子里面第一下的反应就是由于字节序问题造成的.
我起初也是这么想的.因为从出错的现象来看,是某个字段不符合要求造成的出错.于是沿着这个思路去找BUG.抓包来分析,看上去也是这样的.但是,追踪的过程中发现,有多次收发报文的过程,这个字段,或者说拥有这个字段的结构体在多处都有使用,改了一处,在别的地方其它字段又有报错.
回头看代码,发现在最开始解析包头的时候,已经造成了紧跟着包头的某个字段出现异常,于是,想到是不是在不同的平台上,sizeof(某结构体)的数值不一样造成,要验证这一点,给包头结构体的定义加上严格按照一个字节对齐的限制,重新运行程序,可以了.
最后再来稍微详细一些看这个问题,假设包头结构体的定义是:
typedef unsigned short u16;
struct header
{
u16 a;
u16 b;
u16 c;
};
如果解析的时候,sizeof(struct header) != sizeof(u16) * 3,那么使用sizeof(struct header)解析接收到缓冲区的数据就会出现问题,因为它会对紧跟着的数据也造成影响.程序的异常正是源于此.在代码的处理中,首先接收包头,对包头的数据进行了字节序转换,然后,又对紧挨着包头的结构体进行了相同的字节序转换,由于包头结构体的字节序转换同时影响了紧挨着的结构体中的数据,所以这些数据实际上被进行了两次的字节序转换,这才造成了这个问题"看上去"是字节序转换不当造成的"表面原因",如果跟着这个原因继续跟踪下去,以这个思路解决问题,治标而不治本.
总结:
1. 收发数据的结构体定义需要严谨一些,如果不能确定如何对齐,最好自己定义一个对齐的标准.
2. 经验有的时候也不见得就是好事,有时候会让自己陷入思维定式的怪圈,比如在这个问题的处理上,由于问题在切换了硬件平台的时候才出现,正好又是两个字节序不一样的硬件平台,所以经验将我的思路导向了字节序不正确这个方向上.