You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 27 Next »

Reallocation can occur when a member function modifies its container. Modifying member functions include reserve() and resize(), push_back(), pop_back(), erase(), clear(), insert(), and others. In addition, assignment operations and modifying algorithms can also cause reallocation. When a container reallocates its elements, their addresses change. This applies only to contiguous-memory iterators, in particular vector}}s, {{deque}}s and {{string}}s. The {{swap() method of {{string}}s also invalidates iterators.

In general iterators on node-based containers such as {{list}}s are not invalidated via modification of the container, unless the element referenced by the iterator is itself erased.

Pointers and references to objects within a container are also invalidated when iterators are invalidated. A single exception applies for the deque class: it preserves pointers and references to internal objects upon inserts to either its beginning or its end, but it does not preserve iterators.

Consequently, the values of existing iterators may be invalidated [[Kalev 99]]. Using invalid iterators yields undefined results.

Non-Compliant Code Example

In this example, the iterator pos is invalidated after the call to insert, and subsequent loop iterations have undefined behavior.

double data[5] = { 2.3, 3.7, 1.4, 0.8, 9.6 };

deque<double> d;
deque<double>::iterator pos = d.begin();

for (size_t i = 0; i < 5; ++i) {
  d.insert(pos++, data[i] + 41);
}

Compliant Solution 1

Update pos each time insert is called to keep the iterators valid, and then increment it:

double data[5] = { 2.3, 3.7, 1.4, 0.8, 9.6 };

deque<double> d;
deque<double>::iterator pos = d.begin();

for (size_t i = 0; i < 5; ++i) {
  pos = d.insert(pos, data[i] + 41);
  ++pos;
}

Compliant Solution 2

Use one of the STL algorithms.

double data[5] = { 2.3, 3.7, 1.4, 0.8, 9.6 };
deque<double> d;

transform(data, data+5,
    inserter(d, d.begin()),
    bind2nd(plus<int>(), 41));

Risk Assessment

Using invalid iterators yields undefined results.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

ARR32-CPP

3 (high)

2 (probable)

1 (high)

P6

L2

References

[[Meyers 01]] Item 43: Prefer algorithm calls to hand-written loops.
[[Sutter 04]] Item 84: Prefer algorithm calls to handwritten loops.
[[Kalev 99]] ANSI/ISO C++ Professional Programmer's Handbook.
[[ISO/IEC 14882-2003]] Section 24: Iterators Library.


VOID STL00-CPP. Understand how container classes are stored      14. Templates and the STL (STL)      STL31-CPP. Use Valid Iterator Ranges

  • No labels