At what point in the loop does integer overflow become undefined behavior?

后端 未结 12 2241
南方客
南方客 2020-12-07 18:12

This is an example to illustrate my question which involves some much more complicated code that I can\'t post here.

#include 
int main()
{
           


        
12条回答
  •  天命终不由人
    2020-12-07 19:00

    Beyond the theoretical answers, a practical observation would be that for a long time compilers have applied various transforms upon loops to reduce the amount of work done within them. For example, given:

    for (int i=0; i

    a compiler might transform that into:

    int temp = 0;
    for (int i=0; i

    Thus saving a multiplication with every loop iteration. An additional form of optimization, which compilers adapted with varying degrees of aggressiveness, would turn that into:

    if (n > 0)
    {
      int temp1 = n*scale;
      int *temp2 = foo;
      do
      {
        temp1 -= scale;
        *temp2++ = temp1;
      } while(temp1);
    }
    

    Even on machines with silent wraparound on overflow, that could malfunction if there was some number less than n which, when multiplied by scale, would yield 0. It could also turn into an endless loop if scale was read from memory more than once and something changed its value unexpectedly (in any case where "scale" could change mid-loop without invoking UB, a compiler would not be allowed to perform the optimization).

    While most such optimizations would not have any trouble in cases where two short unsigned types are multiplied to yield a value which is between INT_MAX+1 and UINT_MAX, gcc has some cases where such a multiplication within a loop may cause the loop to early-exit. I haven't noticed such behaviors stemming from comparison instructions in generated code, but it is observable in cases where the compiler uses the overflow to infer that a loop can execute at most 4 or fewer times; it does not by default generate warnings in cases where some inputs would cause UB and others would not, even if its inferences cause the upper bound of the loop to be ignored.

提交回复
热议问题