Hi Koen,

On 27.04.2012 15:02, Koen Deforche wrote:
> Hey Stefan,
>
> Op 26 april 2012 18:23 heeft Stefan Ruppert<[email protected]>  het
> volgende geschreven:
>> Hi Koen,
>>
>> today I had some time to debug the crashes with large tree views. In
>> fact I think I have found a serious bug within WStandardItem class.
>>
>> Currently I'm using a WStandardItemModel which is populated with a huge
>> tree. The I use a WSortFilterProxyModel model to support filtering and
>> sorting on that tree. Now whenever a new tree is loaded the old tree is
>> removed be calling removeRows() on the source model. This will result in
>> calling WStandardItem::removeRows() method. And here is a bug during
>> removing rows in conjunction with a WSortFilterProxyModel:
>
> ...
>
>> Here all removed items are deleted before the endRemoveRows() signal is
>> emitted. But within the endRemoveRows() signal the WSortFilterProxyModel
>> removes its source WModelIndex instance which in turn will use the
>> deleted WStandardItem instances!!!
>
> It is legitimate for WStandardItem to delete the items that are in the
> affected rows before calling endRemoveRows(). However, endRemoveRows()
> should not need to "use" these indexes any more (which means: access
> any of its methods -- the object itself is harmless).
>
> WSortFilterProxyModel should not touch these, and indeed
> WSortFilterProxyModel::sourceRowsRemoved() doesn from a first reading
> seem to do this -- it doesn't do anything that is communicated to its
> connected View(s), nor does it try to dereference a model index in the
> region that was deleted ?
>
> When you get the assert, could you get a complete stack trace to see
> how sourceRowsRemoved() is part of it ?

As you can see here sourceRowsRemoved() is involved:

#9  0x00002b977af09472 in Wt::WAbstractProxyModel::shiftModelIndexes #10 
0x00002b977b05b46b in Wt::WSortFilterProxyModel::sourceRowsRemoved

void
WAbstractProxyModel::shiftModelIndexes(const WModelIndex& sourceParent,
                                       int start, int count,
                                       ItemMap& items)
{
   ...
  for (unsigned i = 0; i < erased.size(); ++i) {
     items.erase(erased[i]->sourceIndex_);
     // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This line is the problem
     delete erased[i];
   }
  ...
}

During deletion of the source index from the proxy models item map, the 
depth is calculated by recursively go down to the root in the parent 
chain. And therefore the internal pointer of the sourceIndex_ is used 
which is already deleted!!!

Here is the full stack trace:

#0  0x00002b977b06927d in Wt::WStandardItemModel::headerFlags ()
     at /home/ruppert/work/wt/wt-3.2.1/src/Wt/WStandardItemModel.C:382
#1  0x0000000040ffce90 in ?? ()
#2  0x00002b977b0692eb in global constructors keyed to 
WStandardItemModel.C ()
     at /home/ruppert/work/wt/wt-3.2.1/src/Wt/WFlags:174
#3  0x00002b977b015fb8 in Wt::WModelIndex::parent (this=0x4) at 
/home/ruppert/work/wt/wt-3.2.1/src/Wt/WModelIndex.C:41
#4  0x00002b977b016058 in Wt::WModelIndex::depth (this=<value optimized 
out>)
     at /home/ruppert/work/wt/wt-3.2.1/src/Wt/WModelIndex.C:55
#5  0x00002b977b016060 in Wt::WModelIndex::depth (this=<value optimized 
out>)
     at /home/ruppert/work/wt/wt-3.2.1/src/Wt/WModelIndex.C:55
#6  0x00002b977b016060 in Wt::WModelIndex::depth (this=<value optimized 
out>)
     at /home/ruppert/work/wt/wt-3.2.1/src/Wt/WModelIndex.C:55
#7  0x00002b977b0166dd in Wt::WModelIndex::operator< (this=0x7b3610, 
i2=@0x992888)
     at /home/ruppert/work/wt/wt-3.2.1/src/Wt/WModelIndex.C:88
#8  0x00002b977af09811 in std::_Rb_tree<Wt::WModelIndex, 
std::pair<Wt::WModelIndex const, Wt::WAbstractProxyModel::BaseItem*>, 
std::_Select1st<std::pair<Wt::WModelIndex const, 
Wt::WAbstractProxyModel::BaseItem*> >, std::less<Wt::WModelIndex>, 
std::allocator<std::pair<Wt::WModelIndex const, 
Wt::WAbstractProxyModel::BaseItem*> > >::erase (this=0x6f6270,
     __x=@0x992888)
     at 
/opt/devel/build/x86_64-unknown-linux-gnu/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.3.3/../../../../include/c++/4.3.3/bits/stl_function.h:230
#9  0x00002b977af09472 in Wt::WAbstractProxyModel::shiftModelIndexes 
(this=0x6f6010, sourceParent=@0x40ffd260, start=0,
     count=-1, items=@0x6f6270)
     at 
/opt/devel/build/x86_64-unknown-linux-gnu/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.3.3/../../../../include/c++/4.3.3/bits/stl_map.h:538
#10 0x00002b977b05b46b in Wt::WSortFilterProxyModel::sourceRowsRemoved 
(this=0x40ffce90, parent=@0x6bc6c0, start=4,
     end=<value optimized out>) at 
/home/ruppert/work/wt/wt-3.2.1/src/Wt/WSortFilterProxyModel.C:523
#11 0x00002b977b05cc74 in 
boost::detail::function::void_function_obj_invoker6<boost::_bi::bind_t<void, 
boost::_mfi::mf3<void, Wt::WSortFilterProxyModel, Wt::WModelIndex 
const&, int, int>, 
boost::_bi::list4<boost::_bi::value<Wt::WSortFilterProxyModel*>, 
boost::arg<1>, boost::arg<2>, boost::arg<3> > >, void, Wt::WModelIndex, 
int, int, Wt::NoClass, Wt::NoClass, Wt::NoClass>::invoke 
(function_obj_ptr=<value optimized out>, a0={model_ = 0x0, row_ = 0, 
column_ = 0, internalId_ = 0},
     a1=<value optimized out>, a2=7063232, a3=
         {static none = {static none = <same as static member of an 
already seen type>}}, a4=
         {static none = {static none = <same as static member of an 
already seen type>}}, a5=
         {static none = {static none = <same as static member of an 
already seen type>}})
     at 
/opt/devel/x86_64-unknown-linux-gnu/boost-1.48/include/boost/bind/mem_fn_template.hpp:393
#12 0x00002b977aeec8d2 in boost::signal6<void, Wt::WModelIndex, int, 
int, Wt::NoClass, Wt::NoClass, Wt::NoClass, boost::last_value<void>, 
int, std::less<int>, boost::function6<void, Wt::WModelIndex, int, int, 
Wt::NoClass, Wt::NoClass, Wt::NoClass> >::operator() (this=<value 
optimized out>, a1={model_ = 0x0, row_ = 0, column_ = 0, internalId_ = 
0}, a2=0, a3=0, a4=
         {static none = {static none = <same as static member of an 
already seen type>}}, a5=
         {static none = {static none = <same as static member of an 
already seen type>}}, a6=
         {static none = {static none = <same as static member of an 
already seen type>}})
     at 
/opt/devel/x86_64-unknown-linux-gnu/boost-1.48/include/boost/function/function_template.hpp:760
#13 0x00002b977aeecf83 in Wt::Signal<Wt::WModelIndex, int, int, 
Wt::NoClass, Wt::NoClass, Wt::NoClass>::emit (
     this=0x6bc820, a1={model_ = 0x0, row_ = 0, column_ = 0, internalId_ 
= 0}, a2=0, a3=0, a4=
         {static none = {static none = <same as static member of an 
already seen type>}}, a5=
---Type <return> to continue, or q <return> to quit---
         {static none = {static none = <same as static member of an 
already seen type>}}, a6=
         {static none = {static none = <same as static member of an 
already seen type>}})
     at /home/ruppert/work/wt/wt-3.2.1/src/Wt/WSignal:937
#14 0x00002b977aee73ae in Wt::WAbstractItemModel::endRemoveRows 
(this=0x6bc6c0)
     at /home/ruppert/work/wt/wt-3.2.1/src/Wt/WAbstractItemModel.C:378
#15 0x00002b977b064238 in Wt::WStandardItem::removeRows (this=0x0, 
row=<value optimized out>, count=1)
     at 
/opt/devel/build/x86_64-unknown-linux-gnu/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.3.3/../../../../include/c++/4.3.3/bits/stl_vector.h:688



------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to