From 6dfb7088882e311503bd372db051f07f9747a08b Mon Sep 17 00:00:00 2001 From: d1str4ught <> Date: Mon, 9 Feb 2026 02:25:35 +0100 Subject: [PATCH] crash fix: when __ClearReserveDeleteWindowList() was destroying Windows, some might have pushed it's children for deletion to m_ReserveDeleteWindowList, invalidating iterators --- src/EterPythonLib/PythonWindowManager.cpp | 27 ++++++---- src/EterPythonLib/PythonWindowManager.h | 61 ++++++++++++----------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/src/EterPythonLib/PythonWindowManager.cpp b/src/EterPythonLib/PythonWindowManager.cpp index 3c22f6a..e26da1a 100644 --- a/src/EterPythonLib/PythonWindowManager.cpp +++ b/src/EterPythonLib/PythonWindowManager.cpp @@ -75,6 +75,7 @@ namespace UI void CWindowManager::Destroy() { __ClearReserveDeleteWindowList(); + #ifdef __WINDOW_LEAK_CHECK__ std::set::iterator i; for (i=gs_kSet_pkWnd.begin(); i!=gs_kSet_pkWnd.end(); ++i) @@ -430,7 +431,7 @@ namespace UI pParentWin->DeleteChild(pWin); } pWin->Clear(); - m_ReserveDeleteWindowList.push_back(pWin); + m_ReserveDeleteWindowList.insert(pWin); } BOOL CWindowManager::IsDragging() @@ -710,17 +711,21 @@ namespace UI void CWindowManager::__ClearReserveDeleteWindowList() { - for (TWindowContainer::iterator itor = m_ReserveDeleteWindowList.begin(); itor != m_ReserveDeleteWindowList.end(); ++itor) - { - CWindow * pWin = *itor; -#ifdef __WINDOW_LEAK_CHECK__ - gs_kSet_pkWnd.erase(pWin); -#endif - delete pWin; - } - m_ReserveDeleteWindowList.clear(); + if (m_ReserveDeleteWindowList.empty()) + return; - } + std::unordered_set tmp; + do { + tmp.swap(m_ReserveDeleteWindowList); + for (CWindow* pWin : tmp) { +#ifdef __WINDOW_LEAK_CHECK__ + gs_kSet_pkWnd.erase(pWin); +#endif + delete pWin; + } + tmp.clear(); + } while (!m_ReserveDeleteWindowList.empty()); + } void CWindowManager::Update() { diff --git a/src/EterPythonLib/PythonWindowManager.h b/src/EterPythonLib/PythonWindowManager.h index 40abd42..3c386b7 100644 --- a/src/EterPythonLib/PythonWindowManager.h +++ b/src/EterPythonLib/PythonWindowManager.h @@ -1,4 +1,5 @@ #pragma once +#include namespace UI { @@ -144,44 +145,44 @@ namespace UI void __ClearReserveDeleteWindowList(); private: - long m_lWidth; - long m_lHeight; + long m_lWidth; + long m_lHeight; - int m_iVres; - int m_iHres; + int m_iVres; + int m_iHres; - long m_lMouseX, m_lMouseY; - long m_lDragX, m_lDragY; - long m_lPickedX, m_lPickedY; + long m_lMouseX, m_lMouseY; + long m_lDragX, m_lDragY; + long m_lPickedX, m_lPickedY; - BOOL m_bOnceIgnoreMouseLeftButtonUpEventFlag; - int m_iIgnoreEndTime; + BOOL m_bOnceIgnoreMouseLeftButtonUpEventFlag; + int m_iIgnoreEndTime; // Attaching Icon - PyObject * m_poMouseHandler; - BOOL m_bAttachingFlag; - DWORD m_dwAttachingType; - DWORD m_dwAttachingIndex; - DWORD m_dwAttachingSlotNumber; - BYTE m_byAttachingIconWidth; - BYTE m_byAttachingIconHeight; + PyObject * m_poMouseHandler; + BOOL m_bAttachingFlag; + DWORD m_dwAttachingType; + DWORD m_dwAttachingIndex; + DWORD m_dwAttachingSlotNumber; + BYTE m_byAttachingIconWidth; + BYTE m_byAttachingIconHeight; // Attaching Icon - CWindow * m_pActiveWindow; - TWindowContainer m_ActiveWindowList; - CWindow * m_pLockWindow; - TWindowContainer m_LockWindowList; - CWindow * m_pPointWindow; - CWindow * m_pLeftCaptureWindow; - CWindow * m_pRightCaptureWindow; - CWindow * m_pMiddleCaptureWindow; - TKeyCaptureWindowMap m_KeyCaptureWindowMap; - TWindowContainer m_ReserveDeleteWindowList; - TWindowContainer m_PickAlwaysWindowList; + CWindow * m_pActiveWindow; + TWindowContainer m_ActiveWindowList; + CWindow * m_pLockWindow; + TWindowContainer m_LockWindowList; + CWindow * m_pPointWindow; + CWindow * m_pLeftCaptureWindow; + CWindow * m_pRightCaptureWindow; + CWindow * m_pMiddleCaptureWindow; + TKeyCaptureWindowMap m_KeyCaptureWindowMap; + std::unordered_set m_ReserveDeleteWindowList; + TWindowContainer m_PickAlwaysWindowList; - CWindow * m_pRootWindow; - TWindowContainer m_LayerWindowList; - TLayerContainer m_LayerWindowMap; + CWindow * m_pRootWindow; + TWindowContainer m_LayerWindowList; + TLayerContainer m_LayerWindowMap; }; PyObject * BuildEmptyTuple();