Main Content

AUTOSAR C++14 Rule A23-0-2

Elements of a container shall only be accessed via valid references, iterators, and pointers

Since R2022a

Description

Rule Definition

Elements of a container shall only be accessed via valid references, iterators, and pointers.

Rationale

You access the elements of a container by dereferencing a reference, a pointer, or an iterator. When the size or shape of a container changes, the reference, pointer, or iterator might point to a different element or an invalid location. 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. 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.

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.

Polyspace Implementation

Polyspace® raises a violation of the rule when you access the elements of a container by using a pointer, reference, or iterator that has been invalidated.

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.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#include <iostream>
#include <vector>
#include <algorithm>
#include <list>
void foo()
{
	std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7};
	std::vector<int>::iterator it = std::find(v.begin(), v.end(), 5);
	v.push_back(8);
	std::cout<<*it; //Noncompliant
}

void bar()
{
	std::list<int> l{0, 1, 2, 3, 4, 5, 6, 7};
	std::list<int>::iterator it = std::find(l.begin(), l.end(), 5);
	l.remove(4);
	std::cout<<*it; //Compliant
}

In this example, the function foo() dereferences an iterator it after an insertion. The insertion might trigger a reallocation and invalidate it. Polyspace flags the dereferencing of an iterator that might be invalid.

The function bar() dereferences it after an erasure. The erasure does not invalidate the iterator and Polyspace does not flag the dereferencing.

Check Information

Group: Containers library
Category: Required, Automated

Version History

Introduced in R2022a