取消引用指向不再存在的帧的指针

Dereferencing a pointer to a frame that doesn't exist anymore

本文关键字:指针 存在 不再 引用 取消      更新时间:2023-10-16

我想控制MessagesViewer帧的唯一性,

和这段代码:

MessagesViewer* m_pMsgViewer = NULL;
void Application::ShowMessagesViewer()
{
    if (m_pMsgViewer == NULL)
    {
        m_pMsgViewer = new MessagesViewer(
            wxGetApp().GetContainer()->GetAppData()->GetMessages()
        );
    }
    else
    {
        m_pMsgViewer->FillPage(wxGetApp().GetContainer()->GetAppData()->GetMessages());
        m_pMsgViewer->SetFocus();
    }
}

但是当我第一次调用它时,m_pMsgViewer开始引用内存中的有效数据。当我关闭MessagesViewer帧时,它会自动销毁它,但指针仍然引用旧地址,我无法控制从这个客户端代码销毁帧。

如何解除对销毁帧的指针的引用?

@bogdan已经提出了一个很好的解决方案,但是还有另一个更自动的解决方案:将帧指针存储在wxweakreft <>中。即保持与现在完全相同的代码,但将声明替换为

wxWeakRef<MessagesViewer> m_pMsgViewer;

当窗口被破坏时,弱引用将自动重置为NULL

一个解决方案是在MessagesViewer关闭时将m_pMsgViewer设置回nullptr。一种安全的方法是在框架中添加wxEVT_CLOSE_WINDOW的处理程序。例如,将以下代码添加到MessagesViewer的构造函数中:

Bind(wxEVT_CLOSE_WINDOW, [](wxCloseEvent& evt)
{
   m_pMsgViewer = nullptr;
   evt.Skip();
});

evt.Skip()允许事件进一步传播到wx提供的默认处理程序。

这个简单的例子假设m_pMsgViewer是一个全局变量。如果它实际上包含在Application对象中,则必须添加一些访问它的方法。


MessagesViewer析构函数中添加这样的代码显然不是一个好主意,因为根据文档,MessagesViewer对象的实际销毁是延迟的,因此理论上Application::ShowMessagesViewer()可以在已经关闭并标记为销毁但尚未实际销毁的帧上调用FillPage()

处理close事件会提前重置指针,从而避免上述问题。

您需要以某种方式标记messagesviewer已被销毁并且不能再引用。这意味着除了m_pMsgViewer之外还有一些额外的信息。