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

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 19:19:31

1 现象:问题描述
   话单接口机升级后配置为默认改名方式出错,导致对话单的改名失败。根据日志信息,即使配置为默认改名方式,程序还是读取为自定义改名方式。
2 关键过程:根本原因分析
话单接口在传输话单的过程可以进行改名,可以配置为默认改名方式和自定义改名方式。这是一个一直没有改动的功能,根据前方提供的日志信息,很快定位到改名流程没有走配置的默认改名方式,而是走的自定义改名方式。而自定义改名规则又没有配置,从而导致改名失败。而前方的配置文件确实是配置的默认改名。
为什么配置的是默认改名,程序却按自定义方式改名呢。根据设计,如果改名规则配置项为空则认为是默认改名,否则认为是自定义改名。首先看读配置文件确定改名方式部分代码:
memset(szFileRenameRule, 0, sizeof(szFileRenameRule));
memset(szKey, 0, sizeof(szKey));
sprintf(szKey, "FileRenameRule[%d][%d][%d][%d]", ProcessID, RemoteID, DirID, i);
if ((nRead = CConfig::ReadProfileString("COLLECT",
         szKey,
         szFileRenameRule,
         MAX_RENAMERULELEN,
         RBI_COLLECT_CFG)) <= 0)

    // 读不到配置,或配置为空,那么认为是默认改名
    sTempCollectType.nEnableRename = 1;
    g_Log.WriteLog(LOG_NORMAL, "FileRenameRule[%d][%d][%d][%d]==NULL or No this configure in collection config,set FileRenameRule with default mode",ProcessID, RemoteID, DirID, i);
   memset(sTempCollectType.szFileRenameRule, 0, sizeof(sTempCollectType.szFileRenameRule));
}
else
{
     //自定义改名
     //对字符串进行检验
    memset(sTempCollectType.szFileRenameRule,0,sizeof(sTempCollectType.szFileRenameRule));
    strcpy(sTempCollectType.szFileRenameRule, szFileRenameRule);
    sTempCollectType.nEnableRename = 2;   
}
以上处理读配置流程是正确的一直没有变,但gdb调试发现配置为空时程序走的却是else分支,也就是ReadProfileString函数返回值大于0。再分析ReadProfileString函数的代码,很快发现,读配置的基础函数被修改,如果配置为空不再是返回-1 而是返回一个正数。
int CConfig::ReadProfileString(const char* szAppName, const char* szKeyName, char* szBuf,  int nSize, const char* szFileName)
{
      …
    /* 修改单:V6.0D300 修改人: XXX,XXXXXX   15:23 deled below*/
    /*
    if (strcmp(szBuf, "") == 0)
    {
           //配置为空,返回-1
   return -1;
  }
 */
 /* 修改单:V6.0D300 修改人: XXX,XXXXX  15:23 deled above*/
     …
}
由于修改的版本需要对读取配置为空的情况特别处理,修改了此函数而没有考虑对其他调用此函数的代码。由于基础函数接口改变,带来了很多隐患。
3 结论:解决方案及效果
由于修改读配置基础函数的版本D30只有一个地方调用此函数,而基础版本代码调用此函数众多。为了减少修改代码量和风险,因此修改为兼容老接口,同时增强此函数功能。老接口定义返回值>0表示读取到了配置,返回值表示配置项在配置文件中的行号,<=0表示配置项不存在或配置为空。由于老接口不区分配置项不存在和配置项配置为空的情况,修改为<0表示配置项不存在(返回值表示错误码),==0 表示配置为空,>0 表示读取配置项成功返回行号。新的接口兼容了老接口的定义又可以为D30读取配置为空值提供处理。
4 经验总结:预防措施和规范建议
 在修改基础版本的函数接口时一定要慎重,要充分考虑到接口的兼容,不能只考虑新增功能的要求而随意改变老的接口。
5 备注
6 考核点
修改基础版本函数接口要慎重。
7 试题
1) 软件开发经常是在基础版本上进行增量开发,涉及到新功能和基础版本函数接口时,如下处理说法正确的是( B C )
A) 如果基础版本函数功能不能满足新功能需求,我们修改函数满足我们的新功能就可了。
B) 如果基础版本函数功能不能满足新功能的需求,可以增强此函数功能,但接口和功能必须与基础版本兼容。
C) 如果基础版本函数功能不能满足新功能的需求,可以增加一个新的函数接口封装和增强基础版本函数接口。
D) 以上说法都正确
阅读(367) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~