Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

When two pointers are subtracted, both must point to elements of the same array object or to one past the last element of the array object; the result is the difference of the subscripts of the two array elements. Similarly, when two iterators are subtracted (including via std::distance()), both iterators must refer to the same container object , or must be obtained via a call to end() (or cend()) on the same container object.

If two unrelated iterators (including pointers) are subtracted, the operation results in undefined behavior [ ISO/IEC 14882-2014 ]. Do not subtract two iterators (including pointers) unless both point into the same container , or one past the end of the same container.

...

This noncompliant code example attempts to determine whether the pointer test is within the range [r, r  r + n)]. However, when test does not point within the given range, as in this example, it results undefined behavior.

...

Thus, comparing two pointers which that do not point into the same container , or one past the end of the container , results in unspecified behavior.  While Although the following example is an improvement over the previous noncompliant code example, this example it does not result in portable code and made may fail when executed on a segmented memory architecture (such as some antiquated x86 variants). Consequently, and thus it is noncompliant.

Code Block
bgColor#ffcccc
langcpp
#include <iostream>
 
template <typename Ty>
bool in_range(const Ty *test, const Ty *r, size_t n) {
  return test >= r && test < (r + n);
}
 
void f() {
  double foo[10];
  double *x = &foo[0];
  double bar;
  std::cout << std::boolalpha << in_range(&bar, x, 10);
}

...

This noncompliant code example is roughly equivalent to the previous example , except that it uses iterators in place of raw pointers. As with the previous example, the in_range_impl() function exhibits unspecified behavior when the iterators do not refer into the same container . This is because the operational semantics of a < b on a random access iterator are b - a > 0, and >= is implemented in terms of <.

...

For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.

While Although this approach yields a total ordering, the definition of that total ordering is is still unspecified by the implementation. For instance, the following statement could result in the assertion triggering for a given, unrelated pair of pointers, a and b: assert(std::less<T *>()(a, b) == std::greater<T *>()(a, b));. Consequently, this noncompliant code example is still nonportable and, and indeed on common implementations of std::less<T>, may even result in undefined behavior when the < operator is invoked.

...

In this compliant solution, a fully - portable , but likely inefficient equality comparing test against each possible address in the range [r, n) ] is used to implement the in_range() function:

...

Tool

Version

Checker

Description

PRQA QA-C++

Include Page
PRQA QA-C++_v
PRQA QA-C++_v

2761, 2762, 2763, 2766,

2767, 2768, 2771, 2772,

2773

 

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

...