CAlarmCondManager::AddCond 函数相关代码流程是:生成 CAlarmCond 子类(CDevIDAlarmCond或者CDevTypeAlarmCond)实例,并将实例指针给智能指针管理器 ptrAlarmCond 托管。调用 AddOneCond 函数将ptrAlarmCond托管的CAlarmCond 子类指针保存在 mapAllAlarmConds 中。调用 RecoverOtherAlarms函数后,解除 ptrAlarmCond 对CAlarmCond 子类实例指针的托管。
但问题是,由于没有对调用RecoverOtherAlarms函数进行异常捕获,当RecoverOtherAlarms函数抛异常,则 ptrAlarmCond.release();语句得不到执行机会,直接退出函数。智能指针管理器是栈对象,在函数退栈时,会进行析构,并在自己的析构函数中对托管的CAlarmCond 子类指针进行释放,清理;导致保存在mapAllAlarmConds中的指针为野指针
由于调用CAlarmCondManager::AddCond的外层函数捕获并处理了异常,所以该异常没有引起core.
当后继其他代码使用到 mapAllAlarmConds 中的野指针时会引起core.
追踪日志发现,出现core之前,RecoverOtherAlarms函数确实抛出异常
3 结论:解决方案及效果
解决方案:
CAlarmCondManager::AddCond 函数中增加对调用RecoverOtherAlarms函数的异常捕获处理,当捕获到异常时,执行
ptrAlarmCond.release();
throw;
解除智能指针管理器对托管指针的管理,确保函数CAlarmCondManager::AddCond 调用RecoverOtherAlarms函数异常退出时,智能指针管理器对已经保存在 mapAllAlarmConds 中的指针不进行释放清理,以免导致 mapAllAlarmConds 中出现野指针。同时将异常往上抛,根据本模块代码调用约定,由外层函数处理异常
效果:
按照上面方案修改后,该种类型的core没有重现。问题得到解决。
4 经验总结:预防措施和规范建议
这是一个由于异常未捕获,导致程序指针管理逻辑混乱,产生野指针,从而导致core的典型问题。
调用函数时一定要关注被调函数是否有异常抛出,如果有异常抛出,一定要对异常进行处理
5 备注
无
6 考核点
异常捕获。
7 试题
下列关于异常的描述错误的是()
A:函数设计时,如果有异常抛出,一定要在函数接口说明中明确标示
B:调用函数时,要关注函数是否有异常抛出,如果有异常抛出,一定要进行异常处理
C: 调用函数,为了执行效率,可以不用关注被调函数是否有异常及对异常进行处理
D:异常处理破坏了代码的简洁和紧奏,因此能不处理异常,就不处理异常。
答案:C,D
阅读(433) | 评论(0) | 转发(0) |