这周在某省升级通信中间件,在RedHat平台的中间件 运行正常,业务可以正常处理。但在 HP-UX服务器上,一承载业务,中间件就出Core重启。
我立刻组织部门的同事投入到问题分析中。
首先我在公司的实验室的HP服务器上部署某省的业务。然后在实验室编写votel话务测试脚本,进行业务测试。故障现象浮现,HP下的中间件出core重启。分析代码的位置,是出现在 int i=*(int*)(*begin+1);地方。
然后对版本进行回滚,原来的代码赋值是
+ int i;
+ memcpy((char*)(&i),(*begin)+1,4);
将该处代码由强指针转换改为memcpy后,业务中间件正常运行。
对这个问题百思不得其解,于是我安排小汪在写一个简单的测试程序,代码中只写强制转换的代码。
#include <stdio.h> int main() { char aa[10] = {'a','b','c','d','d','e','f','a','b','c'}; char *p = (aa+0); char *p2 = (aa+0); char **begin = &p2; printf("%p\n",*begin); printf("%p\n",*begin+1); printf("%p\n",**begin); int functionID = *(int*)(*begin+1); printf("functionID=%x\n",functionID); }
用aCC编译后,运行程序,果然出core。
然后改用代码
#include <stdio.h> int main() { char aa[10] = {'a','b','c','d','d','e','f','a','b','c'}; char *p = (aa+0); char *p2 = (aa+0); char **begin = &p2; printf("%p\n",*begin); printf("%p\n",*begin+1); printf("%p\n",**begin); int functionID ; memcpy((char*)&functionID,(*begin)+1,4); printf("functionID=%x\n",functionID); }
aCC编译后运行正常。
小汪跟我说他看到一个帖子,挺有借鉴意义的,具体如下:
概括来讲有的CPU存在内存奇偶的机制,要用偶数内存地址做强制转换。
于是我按照这个文章讲的,对代码又做了修改验证:
#include <stdio.h> int main() { char aa[10] = {'a','b','c','d','d','e','f','a','b','c'}; char *p = (aa+0); char *p2 = (aa+0); char **begin = &p2; printf("%p\n",*begin); printf("%p\n",*begin+1); printf("%p\n",**begin); int functionID = *(int*)(*begin+2); printf("functionID=%x\n",functionID); }
经过aCC编译验证后,程序仍然出core。
然后我接着进行了修改,具体如下:
#include <stdio.h> int main() { char aa[10] = {'a','b','c','d','d','e','f','a','b','c'}; char *p = (aa+0); char *p2 = (aa+0); char **begin = &p2; printf("%p\n",*begin); printf("%p\n",*begin+1); printf("%p\n",**begin); int functionID = *(int*)(*begin+4); printf("functionID=%x\n",functionID); }
对于指针地址+4后,进行强制转换,用aCC编译后运行,程序可以正常运行。
然后我把情况给小汪讲了后,小汪又做了个测试:
#include <stdio.h> int main() { char aa[10] = {'a','b','c','d','d','e','f','a','b','c'}; char *p = (aa+0); char *p2 = (aa+0); char **begin = &p2; printf("%p\n",*begin); printf("%p\n",*begin+1); printf("%p\n",**begin); int functionID = *(short*)(*begin+2); printf("functionID=%x\n",functionID); }
用aCC编译后,程序也可以正常运行。
总结下:
进行数值进行强转赋值需要谨慎,有的CPU存在内存对齐和起始地址的奇偶性。所以尽量用memcpy(类似memcpy((char*)(&i),(*begin)+1,4);),少用类型强转赋值(类似int i=*(int*)(*begin+1);)。