Fix QWidgetItem memory leak in PdmUiFieldEditorHandle destructor

Address sanitizer detected a 1056-byte memory leak in QWidgetItem objects
created when adding widgets to layouts via QGridLayout::addWidget().

Root cause: PdmUiFieldEditorHandle destructor was using deleteLater() to
destroy widgets, but deleteLater() requires an active event loop to process
the delayed deletions. During application shutdown or certain cleanup
scenarios, the event loop may not process these deletions, causing
QWidgetItem objects to remain allocated.

Changes:
- Replace deleteLater() with immediate delete in destructor
- Update comment to explain why immediate deletion is necessary
- This ensures widgets and their associated QWidgetItem objects are
  properly cleaned up when field editors are destroyed

The original comment acknowledged that deleteLater() "will not work unless
you are actually inside an event loop" - this change addresses that issue
by using direct deletion instead.
This commit is contained in:
Kristian Bendiksen committed 2025-09-04 09:04:30 +02:00
1 parent a468e030af
commit 2f4f97c80b
1 file changed
+6 -6
@@ -63,13 +63,13 @@ PdmUiFieldEditorHandle::PdmUiFieldEditorHandle()
//--------------------------------------------------------------------------------------------------
PdmUiFieldEditorHandle::~PdmUiFieldEditorHandle()
{
// Note : deleteLater will not work unless you are actually inside an event loop.
// See https://doc.qt.io/qt-5/qobject.html#deleteLater
// Although it states that they will be deleted at startup of the event loop, it seems as that is not happening.
// Use immediate deletion instead of deleteLater() to prevent memory leaks.
// deleteLater() doesn't work properly during application shutdown when the
// event loop may not process the delayed deletions, causing QWidgetItem leaks.
if ( !m_combinedWidget.isNull() ) m_combinedWidget->deleteLater();
if ( !m_editorWidget.isNull() ) m_editorWidget->deleteLater();
if ( !m_labelWidget.isNull() ) m_labelWidget->deleteLater();
if ( !m_combinedWidget.isNull() ) delete m_combinedWidget;
if ( !m_editorWidget.isNull() ) delete m_editorWidget;
if ( !m_labelWidget.isNull() ) delete m_labelWidget;
}
//--------------------------------------------------------------------------------------------------