Main Content

CERT C++: CTR51-CPP

Use valid references, pointers, and iterators to reference elements of a container

Since R2022a

Description

Rule Definition

Use valid references, pointers, and iterators to reference elements of a container.1

Polyspace Implementation

The rule checker checks for Use of invalid iterator.

Examples

expand all

Issue

Use of invalid iterator occurs when you use an iterator, pointer, or reference to a container element that has been invalidated by actions such as insertion or erasure. For instance, consider this code:

std::vector<int> v = {1,2,3,4,5,6,7};
std::vector<int>::iterator it = std::find(v.begin(), v.end(), 5);
v.push_back(-1);
std::cout<<*it;
If the push_back() operation causes the vector v to reallocate memory to accommodate a larger size, the iterator it is no longer valid. Polyspace® flags the dereferencing of invalid iterators.

Certain erasure operations, such as std::deque::pop_back() or std::forward_list::pop_front() invalidate the iterators to the erased elements. After the erasure, whether any iterators pointed to the erased elements is unknown. If invalidated iterators that point to the erased elements exist in your code, Polyspace does not flag them.

Certain operations return iterators through an std::pair. Polyspace does not track iterators that are part of an std::pair.

Risk

Dereferencing the invalid iterator might produce unexpected results. If the invalidated iterator becomes a dangling pointer or an uninitialized pointer, you might not be able to dereference it safely.

Fix

The C++ standard defined which operations invalidate the iterators of the standard library containers. See Containers library. When performing actions that might invalidate an iterator, validate the iterator, for instance, by recalculating its position.

Example — Avoid Using Invalid Iterators
#include <deque>


void foo(const int *Value, std::size_t count)
{
  std::deque<int> DQ;
  auto It = DQ.begin();
  for (std::size_t i = 0; i < count; ++i, ++It) {
    DQ.insert(It, Value[i] + 42);//Noncompliant
  }
}

In this example, the first DQ.insert() operation invalidates the iterator It. Its subsequent use might result in undefined behavior. Polyspace flags the use of the invalid operator.

Correction — Update the Iterator

When using iterators after an insertion or erasure, update the iterator to avoid undefined behavior. For instance, in this code, It is updated after each insertion so that the iterator remains valid.

#include <deque>


void foo(const int *Value, std::size_t count)
{
  std::deque<int> DQ;
  auto It = DQ.begin();
  for (std::size_t i = 0; i < count; ++i, ++It) {
    It = DQ.insert(It, Value[i] + 41.0);//Compliant
  }
}

Check Information

Group: 04. Containers (CTR)

Version History

Introduced in R2022a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.