Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signed overflow in C++ and undefined behaviour (UB)

I'm wondering about the use of code like the following

int result = 0; int factor = 1; for (...) {     result = ...     factor *= 10; } return result; 

If the loop is iterated over n times, then factor is multiplied by 10 exactly n times. However, factor is only ever used after having been multiplied by 10 a total of n-1 times. If we assume that factor never overflows except on the last iteration of the loop, but may overflow on the last iteration of the loop, then should such code be acceptable? In this case, the value of factor would provably never be used after the overflow has happened.

I'm having a debate on whether code like this should be accepted. It would be possible to put the multiplication inside an if-statement and just not do the multiplication on the last iteration of the loop when it can overflow. The downside is that it clutters the code and adds an unnecessary branch that would need to check for on all the previous loop iterations. I could also iterate over the loop one fewer time and replicate the loop body once after the loop, again, this complicates the code.

The actual code in question is used in a tight inner-loop that consumes a large chunk of the total CPU time in a real-time graphics application.

like image 631
del Avatar asked Nov 29 '19 13:11

del


People also ask

Is signed overflow undefined?

12.2. 1 Basics of Integer Overflow In contrast, the C standard says that signed integer overflow leads to undefined behavior where a program can do anything, including dumping core or overrunning a buffer. The misbehavior can even precede the overflow.

What is undefined Behaviour in C?

So, in C/C++ programming, undefined behavior means when the program fails to compile, or it may execute incorrectly, either crashes or generates incorrect results, or when it may fortuitously do exactly what the programmer intended.

What causes undefined behavior in C?

The program may fail to compile, or it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.” In very simple words, an object when modified more than once between two sequence points will result in undefined behaviour.

Is unspecified behavior undefined behavior?

Unspecified behavior is different from undefined behavior. The latter is typically a result of an erroneous program construct or data, and no requirements are placed on the translation or execution of such constructs.


1 Answers

Compilers do assume that a valid C++ program does not contain UB. Consider for example:

if (x == nullptr) {     *x = 3; } else {     *x = 5; } 

If x == nullptr then dereferencing it and assigning a value is UB. Hence the only way this could end in a valid program is when x == nullptr will never yield true and the compiler can assume under the as if rule, the above is equivalent to:

*x = 5; 

Now in your code

int result = 0; int factor = 1; for (...) {      // Loop until factor overflows but not more    result = ...    factor *= 10; } return result; 

The last multiplication of factor cannot happen in a valid program (signed overflow is undefined). Hence also the assignment to result cannot happen. As there is no way to branch before the last iteration also the previous iteration cannot happen. Eventually, the part of code that is correct (i.e., no undefined behaviour ever happens) is:

// nothing :( 
like image 174
463035818_is_not_a_number Avatar answered Oct 06 '22 22:10

463035818_is_not_a_number