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));
阅读(783) | 评论(0) | 转发(0) |