Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

being sure about "unknown evaluation order"

Tags:

Since version 1.80, Cppcheck tells me that

Expression 'msg[ipos++]=checksum(&msg[1],ipos-1)' depends on order of evaluation of side effects

in this code sequence (simplified, data is a variable)

BYTE msg[MAX_MSG_SIZE];  // msg can be smaller, depending on data encoded int ipos = 0; msg[ipos++] = MSG_START; ipos += encode(&msg[ipos], data); msg[ipos++] = checksum(&msg[1], ipos-1);  // <---- Undefined Behaviour? msg[ipos++] = MSG_END;   // increment ipos to the actual size of msg 

and treats this as an error, not a portability issue.

It's C code (incorporated into a C++-dominated project), compiled with a C++98-complient compiler, and meanwhile runs as expected for decades. Cppcheck is run with C++03, C89, auto-detect language.

I confess that the code should better be rewritten. But before doing this, I try to figure out: Is it really dependent on evaluation order? As I understand it, the right operand is being evaluated first (it needs to before the call), then the assignment is taking place (to msg[ipos]) with the increment of ipos done last.

Am I wrong with this assumption, or is it just a false positive?

like image 588
Wolf Avatar asked Aug 29 '17 11:08

Wolf


People also ask

What does do not depend on the order of evaluation for side effects?

Do not depend on the order of evaluation for side effects unless there is an intervening sequence point. If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

What is the typical evaluation order for an assignment operator?

In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. Whether the left operand is evaluated first or the right operand is evaluated first is not specified by the language.

When an assignment statement is evaluated the first thing that happens is?

The function is called first, the sequence point occurs, it modifies the pointer ppm by pointing it to new allocated struct, followed by a sequence point. Then it stores the value 1000 to the member m , followed by a sequence point.


1 Answers

This code does indeed depend on evaluation order in a way which is not well defined:

msg[ipos++] = checksum(&msg[1], ipos-1); 

Specifically, it is not specified whether ipos++ will increment before or after ipos-1 is evaluated. This is because there is no "sequence point" at the =, only at the end of the full expression (the ;).

The function call is a sequence point. But that only guarantees that ipos-1 happens before the function call. It does not guarantee that ipos++ happens after.

It appears the code should be rewritten this way:

msg[ipos] = checksum(&msg[1], ipos-1); ipos++; // or ++ipos 
like image 99
John Zwinck Avatar answered Sep 24 '22 20:09

John Zwinck