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

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 18:42:35

1 现象:问题描述
A版本上网以后,发现运行几天以后,查询路由的时候EnumDns每次都去EnumServer查询路由,即使是某一个号码多次发送消息以后也不会在本地缓存中查询,而是直接去EnumServer查询路由信息。
在定位的时候发现这个问题比较典型,所以写出来与大家讨论讨论。
2 关键过程:根本原因分析
ENUMDNSAgent接收到查询路由的请求以后,会先在本地的buffer中查询是否有查询的记录,如果原来查询过了,就不去EnumDns中查询路由,直接从本地缓存中读取路由信息。如果查询到数据,那么将查询得到的数据写到本地的缓存中,以便下次查询的时候提高查询的效率。
 
MMS_INT32 CEnumMsgProcess::SearchFromLocal(std::string strRecieveAddr, EnumSubsInfo_S *pstEnumSubsInfo, bool IsSP)
{
bool btmpENumDNSCacheEnable;
     GetENumDNSCacheEnable(btmpENumDNSCacheEnable);
if (!btmpENumDNSCacheEnable)  //不用Cache
{
return FAILURE;
}
 
std::string strTmpPhoneNum = "";
if (!IsSP)
    {―――――――――――――――――――――――――――――――――――(1)
        std::string strTemp = strRecieveAddr.substr(0,1);
        std::string strTmpPhoneNum = "";
        if ("+" == strTemp )
        {
            strTmpPhoneNum = strRecieveAddr.substr(1, strRecieveAddr.length() - 1);
        }
        else
        {
            strTmpPhoneNum = strRecieveAddr;
        }
    }―――――――――――――――――――――――――――――――――――(2)
    else
    {
        if (!AdjustNumber(strRecieveAddr, strTmpPhoneNum))
        {
            return FAILURE;
        }
}
 
    m_mutexTreePhoneNumberPrefix.acquire_read();
    CMatchTree::iterator it = m_ptreePhoneNumberPrefix->find(strTmpPhoneNum);
    if (m_ptreePhoneNumberPrefix->end() != it)
   ……
}
 
检查本地查询的代码,发现一个问题,如上面的代码所示,代码中在不同的范围之内定义了相同的变量名strTmpPhoneNum,但是这两个变量strTmpPhoneNum和strTmpPhoneNum在堆中申请了不同的内存区域,红色的strTmpPhoneNum作用域是(1)和(2)的范围之内,蓝色的strTmpPhoneNum的作用域是除了(1)和(2)的部分,也就是说在(1)和(2)之内strTmpPhoneNum把strTmpPhoneNum屏蔽了。
虽然在(1)和(2)的范围之内strTmpPhoneNum被赋值了,但是在(1)和(2)的范围之外的变量strTmpPhoneNum的值还是为空;
所以在后面去本地的缓存中查询数据的时候,是以空串到map中查询数据,这种情况当然是查询不到数据,在本地查询不到数据,那么按照上图的流程,理所应当到Enum DNS查询数据。
这就是错误的根源。
3 结论:解决方案及效果
修改方法相当简单,把红色的代码直接注释掉就可以了。
发送点到点的流程,第一次EnumDNSAgent会到Enum DNS查询路由,但是第二次就只在本地的缓存中查询路由信息了。
4 经验总结:预防措施和规范建议
其实估计这种问题的出现有几个原因:
(1)对待块代码的拷贝千万要谨慎,因为不同的代码结构对于块拷贝是不一样的过程,而且这种隐藏的错误很难被测试出来;
(2)除非必要,在同一个方法或者函数中尽量不要使用同样的变量名,因为对于不同的变量其作用域是不一样的,也很有可能出现问题,建议把这条加到我们的代码checklist中去。
5 备注
6 考核点
作用域
7 试题
请选择下面的程序的输出: A
int test = 0;
for (int i = 0; i < 3; ++i)
{
    int test = 10;
   
    for (int j = 0; j < 3; ++j)
    {
        test += 1;
    }
   
    printf("%d, ", test);
}
printf("%d", test);
A. 13, 13, 13, 0,  
B. 3, 6, 9, 9
C. 13, 16, 19, 0
D. 13, 16, 19, 19
阅读(238) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~