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

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 19:00:30

1 现象:问题描述
在A版本系统测试中发现添加路由后,网关退出时会Core。
2 关键过程:根本原因分析
跟踪代码发现,网关Core在红色字体标出的代码
    while (pos)
    {
        pDistable = (CDistable*)m_GNSMORouteTable.GetNextItem(pos);
        if (pDistable)
        {
            delete pDistable;
            pDistable = NULL;
        }
    }
通过调试,排除了重复delete的可能性,仔细分析*pDistable的内容,发现问题所在,其虚表指针为0,而CDistable的析构函数是虚函数,因此delete pDistable时,导致网关Core dump。
经过上文分析,可以大体得知问题所在。查找代码中CDistable对象的构造点,发现问题原因。
    // 构建新的路由
    CDistable *pNewDistable = new CDistable;
    if (!pNewDistable)
    {
        return E_MT_NOENOUGH_MEM;
    }
    memset(pNewDistable, 0, sizeof(CDistable));
构造CDistable对象后,使用memset对*pNewDistable初始化,导致虚表也被置0,从而析构时程序Core。
3 结论:解决方案及效果
解决方案很简单,去掉memset语句,成员的初始化在CDistable的构造函数中完成即可。
4 经验总结:预防措施和规范建议
代码中不少地方使用memset对构造的对象进行初始化。如果该类或结构体中仅仅是简单的数据集合,没有虚函数,那么这样做是不存在问题的,否则就会造成意外的灾难。因此使用memset对对象初始化一定要谨慎,就算当前是安全的,将来对类进行扩展也可能会引发问题。类或结构体的成员变量在构造函数中进行初始化是比较安全的。
5 备注
6 考核点
对象的初始化
7 试题
下面会引发问题的代码是 D
A. char *pNew = new char[MAX_ADDR];
memset(pNew, 0, MAX_ADDR);
B. struct tagTest
{
  char szName[MAX_NAME];
  long nLen;
};
 
 tagTest *pTest = new tagTest;
 memset(pTest, 0, sizeof(tagTest));
C. struct tagTest
{
  char szName[MAX_NAME];
  long nLen;
  tagTest()
  {
    memset(szName, 0, sizeof(szName));
    nLen = 0;
  };
};
 tagTest *pTest = new tagTest;
D. struct tagTest
{
  char szName[MAX_NAME];
  long nLen;
  virtual ~tagTest()
  {
    …
  };
};
tagTest *pTest = new tagTest;
memset(pTest, 0, sizeof(tagTest));
阅读(731) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~