Chinaunix首页 | 论坛 | 博客
  • 博客访问: 567458
  • 博文数量: 493
  • 博客积分: 2891
  • 博客等级: 少校
  • 技术积分: 4960
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-17 17:11
文章分类

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 19:32:41

1 现象:问题描述
产品A在测试中偶然发现XXX模块在处理性能告警上报时core,提供core文件和操作日志。产品A运行环境是solaris平台。
2 关键过程:根本原因分析
dbx 分析;core在如下函数红色语句处。
int CPADevMOItem::ParseAlarmCurExplain(char* ExprAlarmVal, const BackAlarmPara AlarmCurVal,
     char* Expr, char* szValueDescSen, char* szAlarmUnit)
{
     。。。
 if(FLOAT_TYPE == AlarmCurVal.AlarmCurValList[nlength].Type)
 {
  
  bool bIfPosNumber = TRUE; //是否是正数
  char szTmpVal[100] = {0};
  char * pPos = NULL;
  int nValTmp;
  char szDecimal[5] = {0};
  char szInteger[50] = {0};
  char szResultVal[50] = {0};
     
  if(AlarmCurVal.AlarmCurValList[nlength].Value.FloatVal() < 0)
  {
   bIfPosNumber = FALSE; //负数
  }
      ACE_OS::sprintf(szTmpVal,"%f",AlarmCurVal.AlarmCurValList[nlength].Value.FloatVal());
  pPos = ACE_OS::strstr(szTmpVal,".");
  //整数部分
  ACE_OS::strncpy(szInteger, szTmpVal, (pPos - szTmpVal) < 50 ? (pPos - szTmpVal) : 50);
  szInteger[49] = '\0';
  //小数部分
  ACE_OS::strncpy(szDecimal, ++pPos, 4);
  szDecimal[3] = '\0';
  int nDecimal = ACE_OS::atoi(szDecimal)
 。。。
}
查看变量值:
。。。
pPos= OXO1
szTmpVal= Inf
。。。
core的原因已经找到:szTmpVal= "Inf", 没有包含小数点".",导致pPos = ACE_OS::strstr(szTmpVal,".")执行后,pPos=0;执行ACE_OS::strncpy(szDecimal, ++pPos, 4);pPos指向0x01(先进行++pPos运算),是一个非法地址,导致core。
但为什么szTmpVal的值为"Inf",异常纳闷,szTmpVal表示一个浮点数值的字符串啊?为什么浮点变成 "Inf" 呢?查询浮点数表示相关资料(参见后面备注),获知:如上"Inf"(Infinity)在浮点数表示中代表正无穷大(浮点数正溢出);
即传进函数的AlarmCurVal.AlarmCurValList[nlength].Value的值由于其他原因(如浮点数相乘等)已经是浮点数正溢出。用ACE_OS::sprintf(szTmpVal,"%f",AlarmCurVal.AlarmCurValList[nlength].Value.FloatVal()) 进行浮点数到字符串的转换,由于浮点数正溢出,所以转换后szTmpVal变为"Inf"。
3 结论:解决方案及效果
解决方案:
增加浮点数溢出保护处理逻辑。关键代码如下所示:
。。。
pPos = ACE_OS::strstr(szTmpVal,".");
if( NULL != pPos )
{
 //整数部分
 ACE_OS::strncpy(szInteger, szTmpVal, (pPos - szTmpVal) < 50 ? (pPos - szTmpVal) : 50);
  szInteger[49] = '\0';
  //小数部分
  ACE_OS::strncpy(szDecimal, ++pPos, 4);
  szDecimal[3] = '\0';
  int nDecimal = ACE_OS::atoi(szDecimal);
    
 }
 else
 {
  ACE_OS::strcpy(szResultVal,(const char*)"INF");
  szResultVal[99] = '\0';
 }
   。。。
效果:
按照上面方案修改后,core问题没有重现。问题得到解决。
阅读(384) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~