Fixed a memory leak in VIEW_ITEM (proper way of doing 9bc2bb2)

The problem with simple deleting VIEW_ITEM_DATA upon VIEW_ITEM removal was
caused by the default copy constructors that copied pointers.
Once a copy of an item was destroyed, the VIEW_ITEM_DATA has been
destroyed, effectively invalidating m_viewPrivData for the other item.
This commit is contained in:
Maciej Suminski 2017-01-16 14:23:22 +01:00
parent 8ac4790370
commit 004ca3c6f9
4 changed files with 14 additions and 31 deletions

View File

@ -55,7 +55,7 @@ public:
~VIEW_ITEM_DATA() ~VIEW_ITEM_DATA()
{ {
delete[] m_groups; deleteGroups();
} }
int getFlags() const int getFlags() const
@ -174,7 +174,7 @@ private:
void deleteGroups() void deleteGroups()
{ {
delete[] m_groups; delete[] m_groups;
m_groups = NULL; m_groups = nullptr;
m_groupsSize = 0; m_groupsSize = 0;
} }
@ -246,7 +246,7 @@ void VIEW::OnDestroy( VIEW_ITEM* aItem )
{ {
auto data = aItem->viewPrivData(); auto data = aItem->viewPrivData();
if(!data) if( !data )
return; return;
data->m_view->Remove( aItem ); data->m_view->Remove( aItem );
@ -311,7 +311,7 @@ void VIEW::Add( VIEW_ITEM* aItem )
aItem->ViewGetLayers( layers, layers_count ); aItem->ViewGetLayers( layers, layers_count );
aItem->viewPrivData()->saveLayers( layers, layers_count ); aItem->viewPrivData()->saveLayers( layers, layers_count );
m_allItems.push_back(aItem); m_allItems.push_back( aItem );
for( int i = 0; i < layers_count; ++i ) for( int i = 0; i < layers_count; ++i )
{ {
@ -360,7 +360,6 @@ void VIEW::Remove( VIEW_ITEM* aItem )
} }
viewData->deleteGroups(); viewData->deleteGroups();
aItem->m_viewPrivData = nullptr;
} }
@ -906,22 +905,13 @@ void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate )
} }
} }
void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate ) void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate )
{ {
for( unsigned int i = 0; i < aGroup->GetSize(); i++) for( unsigned int i = 0; i < aGroup->GetSize(); i++)
draw( aGroup->GetItem(i), aImmediate ); draw( aGroup->GetItem(i), aImmediate );
} }
struct VIEW::unlinkItem
{
bool operator()( VIEW_ITEM* aItem )
{
delete aItem->m_viewPrivData;
aItem->m_viewPrivData = nullptr;
return true;
}
};
struct VIEW::recacheItem struct VIEW::recacheItem
{ {
@ -960,19 +950,10 @@ void VIEW::Clear()
BOX2I r; BOX2I r;
r.SetMaximum(); r.SetMaximum();
m_allItems.clear(); m_allItems.clear();
for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i ) for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i )
{ i->second.items->RemoveAll();
VIEW_LAYER* l = &( ( *i ).second );
unlinkItem v;
if( m_dynamic )
l->items->Query( r, v );
l->items->RemoveAll();
}
m_gal->ClearCache(); m_gal->ClearCache();
} }
@ -1265,9 +1246,10 @@ void VIEW::UpdateItems()
continue; continue;
if( viewData->m_requiredUpdate != NONE ) if( viewData->m_requiredUpdate != NONE )
{
invalidateItem( item, viewData->m_requiredUpdate ); invalidateItem( item, viewData->m_requiredUpdate );
viewData->m_requiredUpdate = NONE;
viewData->m_requiredUpdate = NONE; }
} }
m_gal->EndUpdate(); m_gal->EndUpdate();

View File

@ -50,8 +50,7 @@ VIEW_GROUP::VIEW_GROUP( VIEW* aView ) :
VIEW_GROUP::~VIEW_GROUP() VIEW_GROUP::~VIEW_GROUP()
{ {
if( m_view && viewPrivData() ) // VIEW_ITEM destructor removes the object from its parent view
m_view->Remove( this );
} }

View File

@ -84,11 +84,13 @@ class VIEW_ITEM
public: public:
VIEW_ITEM() : m_viewPrivData( nullptr ) VIEW_ITEM() : m_viewPrivData( nullptr )
{ {
} }
virtual ~VIEW_ITEM(); virtual ~VIEW_ITEM();
VIEW_ITEM( const VIEW_ITEM& aOther ) = delete;
VIEW_ITEM& operator=( const VIEW_ITEM& aOther ) = delete;
/** /**
* Function ViewBBox() * Function ViewBBox()
* returns the bounding box of the item covering all its layers. * returns the bounding box of the item covering all its layers.

View File

@ -449,7 +449,7 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
return 0; return 0;
// Get a copy instead of a reference, as we are going to clear current selection // Get a copy instead of a reference, as we are going to clear current selection
SELECTION selection = m_selectionTool->GetSelection(); auto selection = m_selectionTool->GetSelection().GetItems();
// As we are about to remove items, they have to be removed from the selection first // As we are about to remove items, they have to be removed from the selection first
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );