需要实现通信功能,在项目代码中调用通信库接口函数:
void A(Struct_Test *testData, ……)
结构体:
typedef struct {
struct A;
struct B;
TCHAR data1[PARA_MAX + 1];
…
} Struct_Test ;
由于在项目中调用函数接口A,总是后续死在通信库的其余部分代码中,初步打分析后发现,传入函数接口A中的结构体Struct_Test 的参数与调用接口前填的参数不一致。
检查代码并没有发现调用方式的问题(很简单的直接调用),进一步分析发现传入函数A前的结构体中成员的地址与传入后的指针地址不同,仅第一个成员的地址没有问题,于是怀疑项目代码中的结构体与通信库中的结构体不是同一个?
怀着这个疑问,又打印了调用前和接口函数中,结构体的大小:sizeof(Struct_Test),发现,调用后的大小是调用前大小的一倍多一点点,这个一倍多一点点,一下就给我提供了方向,结合起来有了几个待确认的点:
- 两份代码中结构体是否是同一个还没得到解决?
- 可能是两份代码一个32位一个64位编译的结果?
- 是否是字节对齐问题导致大小不一致?
- 是否两份代码的字符集不一致?
第一个问题,之后在结构体中写了一个构造函数,在调用接口前后,创建了一个对象,确认了两份代码的结构体为同一个
第二个问题,检查了一下两边的编译坏境,确认都是在32位下进行编译
第三个问题,在结构体定义处使用#program pack(1)指定了字节对齐,结果发现并没有变化
第四个问题,检查两边代码的字符集后发现,项目代码为多字节字符,而通信库为Unicode,这回导致项目代码中TCHAR的大小为1,而通信库中的TCHAR大小为2。
接近真相了,此时的问题,如果仅仅是字符集的问题,那么应该传入前后结构体大小刚好为两倍,为何多出一点?
代码对比工具对比结构体处代码后,并没有发现问题,最后由于突然想到,此项目的代码是陈年老代码,凭着以往经验,顺手检查了一下,项目依赖,发现问题!
由于项目代码中包含该结构体的头文件在SVN上是固定的版本,没有根据通信库代码的更改自动拉取全新代码,导致结构体中的宏:PARA_MAX 大小的定义两份代码中定义不同,造成总的结构体大小有细微偏差,解决这些问题后,重新编译,运行程序,解决!
总结,自己之前较少对成员大小,字节对齐,编码方面有关注,解决这个问题的过程中,学到了许多知识,还包括后续为了项目代码可以在Unicode下编译成功,做了一系列数据类型转换的工作,巩固了一下数据类型转换的知识:一些常用多字节宽字节字符转换接口(https://editor.youkuaiyun.com/md/?articleId=129807325)。