[GiNaC-devel] Questions about expairseq::match().
Jens Vollinga
jensv at nikhef.nl
Tue Jul 15 08:58:09 CEST 2008
Hi,
see
http://www.ginac.de/pipermail/ginac-devel/2006-April/000942.html
for an explanation.
Alexei Sheplyakov schrieb:
> This fragment looks a bit confusing. it->match(p, repl_lst) can change
> repl_lst, so iterators become invalid. Fortunately, in that case match
> returns true, so we jump out of the loop. So, we can initialize
> the iterator last_el *after* checking for possible matches, like this:
>
> if (it->match(p, repl_lst)) {
> ops.erase(it);
> goto found;
> }
> lst::const_iterator last_el = repl_lst.end();
> --last_el;
>
> Unless I'm missing something this code is equivalent to the previous
> variant, but it's more readable (i.e. no confusion about possible invalidation
> of last_el iterator).
It also looks strange to me, but I am not 100% sure whether it is wrong
or serves some purpose, yet.
> 436 while(true) {
> 437 lst::const_iterator next_el = last_el;
> 438 ++next_el;
> 439 if(next_el == repl_lst.end())
> 440 break;
> 441 else
> 442 repl_lst.remove_last();
> 443 }
>
> There's definitely something fishy about this chunk. First of all, it seems
> like next_el at the line 439 is always repl_lst.end(), so this code doesn't
> do anything at all. Secondly, if it next_el ever changes its value from
> repl_lst.end(), repl_lst.remove_last() invalidates iterators (both next_el
> *and* last_el), so the result of next iteration is unpredictable.
First, in the current code last_el can be different from repl_lst.end()
if in line 432 the call to match changes repl_lst.
Second, (almost) no iterators are invalidated here. These are list
iterators, not vector or deque iterators! The "almost" refers to the
recursive call of match in line 432. Obviously, repl_lst is expected to
change, but the code seems to be okay only for the case that the last
element in repl_lst is not deleted. I am not sure about this yet, as I
wrote above.
Regards,
Jens
More information about the GiNaC-devel
mailing list