Wxwidget wxTimer 在应用程序关闭时导致随机访问冲突

Wxwidget wxTimer causes random access violation on application close

我在使用 wxWidgets v3.0.1 的 wxFrame window 上有一个相当简单的 wxTimer 循环,它在处理关闭事件时随机导致访问冲突(例如 file/exit 或对话框框架上的 X) , 然后在 destroy();

之前调用 m_timer.stop()

我已经通过 Whosebug 进行了挖掘,并尝试了所有我能找到的方法,但都无济于事。任何人都可以指出我可能出错的地方吗:

系统: 我在 wxApp class 中创建了一个应用程序 class 并(通过指针)传递给 wxFrame、wxPanel,因为我正在使用 wxAuiManager。

定时器正在初始化:

m_timer.SetOwner( this, ID_toolbarPaneTimer );
m_timer.Start( 2000, wxTIMER_CONTINUOUS );    

Connect( ID_toolbarPaneTimer
       , wxEVT_TIMER
       , wxTimerEventHandler( ToolbarPane::OnTimerTick ) );

::OnTimerTick函数本身也很简单:

void ToolbarPane::OnTimerTick( wxTimerEvent &event )
{
    AssetDataTransaction *transaction = NULL;
    int transactionsWaiting = m_projectModel->GetNumberOfAssetTransactions();

    if ( transactionsWaiting > 0 )
    {
        for ( int transNo = 0; transNo < transactionsWaiting; transNo++ )
        {
            transaction = m_projectModel->GetTopAssetTransaction();

            switch( transaction->GetType() )
            {
            case AssetDataTransactionType_add:
                AddAssetItem( transaction );
                m_projectModel->PopTopAssetTransaction();
                break;

            default:
                break;
            }
        }
    }
}

当主对话框关闭时,工具栏窗格会执行 m_timer.stop()。当 wxApp 被销毁时,应用程序 class 也被销毁。

访问冲突中断于:

void wxTimerHiddenWindowModule::OnExit()
{
    if ( ms_hwnd )
    {
        if ( !::DestroyWindow(ms_hwnd) )
        {
            wxLogLastError(wxT("DestroyWindow(wxTimerHiddenWindow)"));
        }

任何关于我做错的建议都将不胜感激。

更新:

  1. 已检查 m_projectModel 的空指针,但没有帮助
  2. 我删除了计时器中的所有代码,但它仍然崩溃
  3. 已验证 3.0.2 更改日志中未添加任何计时器修复程序
  4. 应用程序没有创建任何其他线程。

我发现问题不是wxWidgets本身引起的,而是第三方应用引起的。

OP 在 Mac 上的 Parallels 虚拟机中 运行 Windows,处于 Coherence View 模式。安装在 Windows 中的 Parallels Tools 组件在此配置中使用了一个挂钩 DLL (prl_hook.dll),它被注入所有进程并检查 window 管理调用,包括 ::DestroyWindow()

wxWidgets 使用隐藏的 window 来接收 wxTimer 事件。 window 由 wxTimerHiddenWindowModule 管理。 Parallels 挂钩 DLL 不喜欢这样 window - 当 wx 在其上调用 ::DestroyWindow() 作为应用程序退出时正常清理过程的一部分时,挂钩 DLL 代码有时会因访问冲突而崩溃。

停止 Parallels Tools 服务解决了问题。