首页 > 代码库 > wxWidgets第十六课 wxTimer没有调用stop导致崩溃的问题分析

wxWidgets第十六课 wxTimer没有调用stop导致崩溃的问题分析

场景

   调用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) 行 4 C++

        __tmainCRTStartup() 行 528 C


经验

如果只是根据这些信息,显然没有任何的实际意义,从而引出下文的重点:当出现程序崩溃的时候,需要从当前的堆栈信息,不断的从最新的函数调用往前进行回溯,指向WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow) 行 4 C++这一句的指针式白色的,而在调用堆栈的列表上,还有其他的信息,尤其是最前面的黄色的指针指向的内容: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

从上面看到定时器的继承关系


wxWidgets第十六课 wxTimer没有调用stop导致崩溃的问题分析