十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
场景
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:国际域名空间、虚拟主机、营销软件、网站建设、鹿泉网站维护、网站推广。
调用wxTimer定时器功能的时候,如果关闭当前的窗口,会出现上述的问题:0xC0000005: 读取位置 0xFEEEFF06 时发生访问冲突
说明
跟踪调用堆栈的具体情况,代码崩溃点指向IMPLEMENT_APP(CTestApp)
调用堆栈指向:
wxEntry(int &,wchar_t * *)未知
wxEntry(struct HINSTANCE__ *,struct HINSTANCE__ *,char *,int)未知
>WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow) 行 4C++
__tmainCRTStartup() 行 528C
经验
如果只是根据这些信息,显然没有任何的实际意义,从而引出下文的重点:当出现程序崩溃的时候,需要从当前的堆栈信息,不断的从最新的函数调用往前进行回溯,指向WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow) 行 4C++这一句的指针式白色的,而在调用堆栈的列表上,还有其他的信息,尤其是最前面的×××的指针指向的内容:wxEvtHandler::SafelyProcessEvent(class wxEvent &)未知,经过不断的回溯,才知道是wxTimerImpl发生错误,明显的这是一个定时器,而在程序中确实使用了定时器,现在已经锁定了目标,分析问题就不会太难了。之前没有分析出问题,就是没有逐一分析调用堆栈,看不懂系统调用没有关系,关键是哪些用户的调用会触发系统的调用从而导致问题的出现
跟踪调用堆栈
wxEvtHandler::SafelyProcessEvent(class wxEvent &)未知
wxTimerImpl::SendEvent(void)未知
wxTimerWndProc(struct HWND__ *,unsigned int,unsigned int,long)未知
说明在定时器处理消息的时候出现了问题,此时关闭窗口,应该已经销毁了定时器的实例指针,这个时候定时器应该接收不到任何的消息,但是从调用堆栈来看,定时器内部还是继续在处理消息,导致了问题的出现
查看代码
声明:wxTimer *m_timer;
创建对象:m_timer = new wxTimer(this, TIMER_ID);
启动定时器:m_timer->Start(10);
结论
这里就有一个问题了,没有停止定时器,但是就算没有停止,发生的最终原因又是为何?当然了,通过在关闭窗口之前,调用m_timer->Stop(),停止定时器,解决了该问题
扩展
class WXDLLIMPEXP_BASE wxTimer : public wxEvtHandler
class WXDLLIMPEXP_BASE wxEvtHandler : public wxObject
, public wxTrackable
从上面看到定时器的继承关系