Main Content

MISRA C++:2023 Rule 4.6.1

Operations on a memory location shall be sequenced appropriately

Since R2024b

Description

Rule Definition

Operations on a memory location shall be sequenced appropriately.

Rationale

Operations on a memory location are unsequenced if the compiler is permitted to evaluate the operations in any order and to overlap their evaluation. If any of the operations has a side effect, then unsequenced access can result in undefined behavior.

Operations on a memory location are indeterminately sequenced if the compiler is permitted to evaluate the operations in any order, but is not permitted to overlap their evaluation. The output of indeterminately sequenced operations depends on the order of evaluation that the compiler chooses.

To avoid undefined behavior and implementation-defined behavior, use sequenced before operations. The order of evaluation of sequenced before operations is well-defined. See eval_order.

Appropriateness of an operation sequencing can change depending on the C++ standard you use. C++17 changed the evaluation order of certain expressions to sequenced before. For example, C++17 specifies that the evaluation of the right side of an assignment operation is sequenced before the evaluation of the left hand side. The evaluation order of this expression is well-defined in C++17 but unspecified in older C++ standards. This operation sequencing is appropriate and compliant to this rule for C++17, but results in a violation of this rule for older C++ standards.

a[i++] = b[i++]; //Compliant in C++17

Polyspace Implementation

Polyspace® reports a violation of this rule if an expression satisfies any of these conditions:

  • A variable in the expression is modified more than once or it is both read and written.

  • An expression allows more than one order of evaluation that can lead to different results.

  • An expression contains a single volatile object that occurs multiple times.

  • An expression contains more than one volatile object.

Because volatile objects can change their value at any time, an expression containing multiple volatile objects or multiple instances of the same volatile object can produce different results depending on the order of evaluation.

When checking an expression containing function calls, Polyspace checks the body of the called functions. If the function body contains calls to other functions, their bodies are not checked. For instance:

int f1() {return 1;}
int f2() {return g();}
int g() {return 2;}

void foo(void) {
	int z = f1() + f2();
}
When checking the expression z = f1()+f2(), Polyspace checks the body of f1() and f2(), but does not check the body of g()

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

In this example, the rule is violated because it is unspecified whether the operation i++ occurs before or after the second argument is passed to f(). The compiler can evaluate f(i++,i) as either f(0,0) or f(0,1).

void f(unsigned int param1, unsigned int param2) {}

void main() {
	unsigned int i = 0;
	f(i++, i);                    // Noncompliant
}

In this example, this rule is violated twice.

volatile int a, b;
int mathOp(int x, int y);

int foo(void) {
	int temp = mathOp(5, a) + mathOp(6, b); //Noncompliant
	return temp * mathOp(a, a); //Noncompliant
}

  • The declaration of temp uses two volatile objects. Because the value of volatile objects can change at any time, the expression might evaluate to different values depending on the order of evaluation. Polyspace reports a violation for the second volatile object in the expression.

  • The return statement uses the same volatile object twice. Because the expression might evaluate to different values depending on the order of evaluation, Polyspace reports a violation of this rule.

Check Information

Group: General Principles
Category: Required

Version History

Introduced in R2024b