From b27176f2303f9eceaf077685aba85e710254bced Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Wed, 23 Sep 2015 19:02:40 -0400 Subject: [PATCH] Pcbnew: fix segfault after deleting a pad from a footprint then performing a DRC action such as a via drag. --- pcbnew/block_module_editor.cpp | 16 +++++++--------- pcbnew/class_board.cpp | 8 ++++++++ pcbnew/class_board.h | 8 ++++++++ pcbnew/class_netinfo.h | 23 +++++++++++++++++++---- pcbnew/class_netinfolist.cpp | 3 +++ pcbnew/drc_clearance_test_functions.cpp | 4 +++- pcbnew/pad_edition_functions.cpp | 4 +++- 7 files changed, 51 insertions(+), 15 deletions(-) diff --git a/pcbnew/block_module_editor.cpp b/pcbnew/block_module_editor.cpp index 1ec2447fde..21d100b9c5 100644 --- a/pcbnew/block_module_editor.cpp +++ b/pcbnew/block_module_editor.cpp @@ -537,29 +537,27 @@ void MoveMarkedItems( MODULE* module, wxPoint offset ) */ void DeleteMarkedItems( MODULE* module ) { - BOARD_ITEM* item; BOARD_ITEM* next_item; - D_PAD* pad; D_PAD* next_pad; + BOARD* board = module->GetBoard(); if( module == NULL ) return; - pad = module->Pads(); - - for( ; pad != NULL; pad = next_pad ) + for( D_PAD* pad = module->Pads(); pad; pad = next_pad ) { next_pad = pad->Next(); if( !pad->IsSelected() ) continue; - pad->DeleteStructure(); + if( board ) + board->PadDelete( pad ); + else + pad->DeleteStructure(); } - item = module->GraphicalItems(); - - for( ; item != NULL; item = next_item ) + for( BOARD_ITEM* item = module->GraphicalItems(); item; item = next_item ) { next_item = item->Next(); diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index d4e8d39ea3..8c474fbf2c 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -1666,6 +1666,14 @@ void BOARD::GetSortedPadListByXthenYCoord( std::vector& aVector, int aNe } +void BOARD::PadDelete( D_PAD* aPad ) +{ + m_NetInfo.DeletePad( aPad ); + + aPad->DeleteStructure(); +} + + TRACK* BOARD::GetTrack( TRACK* aTrace, const wxPoint& aPosition, LSET aLayerMask ) const { diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 6510b89514..8836e151f9 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -1274,6 +1274,14 @@ public: */ D_PAD* GetPad( std::vector& aPadList, const wxPoint& aPosition, LSET aLayerMask ); + /** + * Function PadDelete + * deletes a given bad from the BOARD by removing it from its module and + * from the m_NetInfo. Makes no UI calls. + * @param aPad is the pad to delete. + */ + void PadDelete( D_PAD* aPad ); + /** * Function GetSortedPadListByXthenYCoord * first empties then fills the vector with all pads and sorts them by diff --git a/pcbnew/class_netinfo.h b/pcbnew/class_netinfo.h index 85dbc70167..8fb74d50e4 100644 --- a/pcbnew/class_netinfo.h +++ b/pcbnew/class_netinfo.h @@ -304,9 +304,8 @@ public: /** * Function GetPads - * returns a list of all the pads. The returned list is not - * sorted and contains pointers to PADS, but those pointers do not convey - * ownership of the respective PADs. + * returns a list of all the pads (so long as buildPadsFullList() has + * been recently called). Returned list contains non-owning pointers. * @return std::vector& - a full list of pads std::vector& GetPads() { @@ -326,6 +325,22 @@ public: return NULL; } + bool DeletePad( D_PAD* aPad ) + { + std::vector::iterator it = m_PadsFullList.begin(); + std::vector::iterator end = m_PadsFullList.end(); + + for( ; it != end; ++it ) + { + if( *it == aPad ) + { + m_PadsFullList.erase( it ); + return true; + } + } + return false; + } + ///> Constant that holds the "unconnected net" number (typically 0) ///> all items "connected" to this net are actually not connected items static const int UNCONNECTED; @@ -409,7 +424,7 @@ public: private: /** - * Function DeleteData + * Function clear * deletes the list of nets (and free memory) */ void clear(); diff --git a/pcbnew/class_netinfolist.cpp b/pcbnew/class_netinfolist.cpp index 2e03c86b50..74b11bfa8d 100644 --- a/pcbnew/class_netinfolist.cpp +++ b/pcbnew/class_netinfolist.cpp @@ -144,6 +144,7 @@ void NETINFO_LIST::buildListOfNets() // Add pad to the appropriate list of pads NETINFO_ITEM* net = pad->GetNet(); + // it should not be possible for BOARD_CONNECTED_ITEM to return NULL as a result of GetNet() wxASSERT( net ); @@ -162,6 +163,7 @@ void NETINFO_LIST::buildListOfNets() m_Parent->SetAreasNetCodesFromNetNames(); } + #if defined(DEBUG) void NETINFO_LIST::Show() const { @@ -176,6 +178,7 @@ void NETINFO_LIST::Show() const } #endif + void NETINFO_LIST::buildPadsFullList() { /* diff --git a/pcbnew/drc_clearance_test_functions.cpp b/pcbnew/drc_clearance_test_functions.cpp index e524336b54..39d1b9d039 100644 --- a/pcbnew/drc_clearance_test_functions.cpp +++ b/pcbnew/drc_clearance_test_functions.cpp @@ -272,7 +272,9 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) // Compute the min distance to pads if( testPads ) { - for( unsigned ii = 0; iiGetPadCount(); ++ii ) + unsigned pad_count = m_pcb->GetPadCount(); + + for( unsigned ii = 0; iiGetPad( ii ); diff --git a/pcbnew/pad_edition_functions.cpp b/pcbnew/pad_edition_functions.cpp index 0cf012dfef..e1b87ed90a 100644 --- a/pcbnew/pad_edition_functions.cpp +++ b/pcbnew/pad_edition_functions.cpp @@ -220,7 +220,9 @@ void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery ) EDA_RECT bbox = module->GetBoundingBox(); m_Pcb->m_Status_Pcb = 0; - aPad->DeleteStructure(); + + GetBoard()->PadDelete( aPad ); + // Update the bounding box module->CalculateBoundingBox();