这周在某省升级通信中间件,在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);)。