1 现象:问题描述
在P产品系统测试时,测试部提了个问题单,在呼叫处理流程中,用户自动应答时,程序发现core.
2 关键过程:根本原因分析
由于此core文件直接指向的源代码行数(下面红色部分),用gdb观察对应对象指针已经是个野指针了.
void FatherHandler::DoResponse(BaseResponse* pResponse)
{
//临时响应
if (Code >100 && Code < 200)
{
OnProvisonalResponse();
DELETE(m_pDownResponse);
DELETE(m_pUpResponse);
}
}
Void SunHanler:: OnProvisonalResponse()
{
......
m_pHandlerObserver->NotifyEvent(connectedEvent)
}
其中,sunHanler是FatherHandler的子类,m_pUpResponse,m_pDownResponse均为FatherHanlder成员变量.在执行 m_pHandlerObserver->NotifyEvent(connectedEvent)时,会动态删除sunHanler的实例,使得执行SunHanler:: OnProvisonalResponse()完毕后,继续执行FatherHandler::DoResponse(),由于该实现已经被释放,导致执行DELETE(m_pDownResponse)是对无效对象的成员m_pDownResponse进行非法访问,实际上此时m_pDownResponse已经是野指针了.
3 结论:解决方案及效果
解决的方法为:Void SunHanler:: OnProvisonalResponse()不执行下面语句m_pHandlerObserver->NotifyEvent(connectedEvent)接口.修改代码后,用工具反复测试,未发现异常.
4 经验总结:预防措施和规范建议
1. 野指针是c++编程常见的棘手严重问题,编码时应注重review工作,关注对象的生命周期管理
2. 做好测试,特别是使用工具进行指针访问的检测,如purify对于野指针的访问能及时报错提示.
5 备注
6 考核点
野指针,
7 试题
#include "stdafx.h"
#include "list"
class msg
{
public:
int m_id;
};
class HandlerObserver;
class BaseObserver
{
public:
virtual void NotifyEnd() = 0;
};
class Basehandler
{
public:
Basehandler(){m_pMsg = NULL;};
virtual ~Basehandler()
{
printf("~Basehandler()");
if(NULL != m_pMsg)
{
delete m_pMsg;
}
}
void doMsg(msg* pMsg)
{
m_pMsg = pMsg;
doReq(m_pMsg);
delete m_pMsg;
m_pMsg = NULL;
}
virtual void doReq(msg *pMsg) = 0;
void setObserver(BaseObserver* pObserver){m_pObserver = pObserver;};
protected:
msg* m_pMsg;
BaseObserver* m_pObserver;
};
class MsgHandler:public Basehandler
{
public:
MsgHandler(){};
void doReq(msg* pMsg)
{
m_pObserver->NotifyEnd();
};
};
class HandlerObserver:public BaseObserver
{
public:
void doMsg(msg* pMsg)
{
m_pHandler = new MsgHandler();
m_pHandler->setObserver(this);
m_pHandler->doMsg(pMsg);
}
void NotifyEnd()
{
if(NULL != m_pHandler)
{
delete m_pHandler;
m_pHandler = NULL;
}
}
private:
Basehandler* m_pHandler;
};
int main(int argc, char* argv[])
{
msg* pMsg = new msg();
pMsg->m_id = 1;
HandlerObserver Observer;
Observer.doMsg(pMsg);
printf("%d",pMsg->m_id);
return 0;
}
在windows运行上面,下面说法完全正确的是:C
A 屏幕上输出~Basehandler()1,
B 屏幕上输出1
C 屏幕输出~BaseHanler后弹出异常
D 上述说法均不正确
阅读(506) | 评论(0) | 转发(0) |