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

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 19:39:59

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) |
给主人留下些什么吧!~~