mirror of https://github.com/YosysHQ/yosys.git
proc_prune: avoid using invalidated iterator
An `std::vector<T>::reverse_iterator` stores the `std::vector<T>::iterator` which points to the (forwards-ordered) *following* item. Thus while `vec.rbegin()` dereferences to the final item of `vec`, the iterator it wraps (`vec.rbegin().base()`) is equal to `vec.end()`. In the remove case here, we advance `it` (backwards), erasing the item we just advanced past by grabbing its (pre-increment) base forward-iterator and subtracting 1. The iterator maths here is obviously all OK, but the forward-iterator that `it` wraps post-increment actually points to the item we just removed. That iterator was invalidated by the `erase()` call. That this works anyway is (AFAICT) some combination of luck and/or promises that aren't part of the C++ spec, but MSVC's debug iterator support picks this up. `erase()` returns the new iterator that follows the item just erased, which happens to be the exact one we want our reverse-iterator to wrap for the next loop; we get a fresh iterator to the same base, now without the preceding item.
This commit is contained in:
parent
104edb4587
commit
63e4114233
|
@ -91,7 +91,7 @@ struct PruneWorker
|
|||
if (GetSize(new_lhs) == 0) {
|
||||
if (GetSize(conn_lhs) == 0)
|
||||
removed_count++;
|
||||
cs->actions.erase((it++).base() - 1);
|
||||
it = decltype(cs->actions)::reverse_iterator(cs->actions.erase(it.base() - 1));
|
||||
} else {
|
||||
it->first = new_lhs;
|
||||
it->second = new_rhs;
|
||||
|
|
Loading…
Reference in New Issue