2

Is it possible to detect or prevent integer overflow at compile-time and not at run-time?

If the overflow is not detected and it occurs at run-tine is it possible to be detected? I read somewhere that the processor will have a specific flag set in case there is an overflow at a an operation.

How to read the specific flags of the processor? Should I ask this as a separate question?

EDIT:

My question was about both signed and unsigned overflow. When we have an unsigned variable it can still overflow and set itself to 0 or something close to 0, right? Or is it something that I am missing?

  • 1
    Read about the Halting Problem. If you solve this, you answered your question. How do you think the compiler is supposed to detect overflow e.g. for values you enter at run-time? And for signed, if the overflow happend, it already did invoke UB. – too honest for this site Sep 19 '17 at 12:02
  • 2
    Possible duplicate of [Detecting signed overflow in C/C++](https://stackoverflow.com/questions/3944505/detecting-signed-overflow-in-c-c) – too honest for this site Sep 19 '17 at 12:05
  • 2
    It is possible but it is not implemented in C or C++. If you want to shot yourself in the leg, then C and C++ will allow you to. There is already a question about [processor flags](https://stackoverflow.com/questions/791991/about-assembly-cfcarry-and-ofoverflow-flag). – user7860670 Sep 19 '17 at 12:07
  • 3
    @VTT: No, this is not possible. OP asks about detecting at **compile-time**. About the flags: please provide a reference to the any of both standards specifying them. Signed overflow is UB, once occured, it is too late. You hve to **avoid** it. – too honest for this site Sep 19 '17 at 12:09
  • 1
    @Olaf the second part of the question is definitely about the runtime (or maybe I do know how to read the processor flags during the compilation) – 0___________ Sep 19 '17 at 12:12
  • 1
    @Jennifer: The processor flags (runtime) would be a different question. But to preempt you there: that's not how C or C++ work. The compiler might not be generating the code you're thinking it's generating, and may not even set these flags (especially on ARM, where this would be entirely unexpected). – MSalters Sep 19 '17 at 12:14
  • 2
    @Olaf you are arguing from the standpoint of the standard. The question mentions reading specific flags of the processor which means that we are in the platform-specific domain. Thus, your argument about UB visavi the standard no longer holds. – Klas Lindbäck Sep 19 '17 at 12:17
  • 2
    @Olaf It is possible at compile time, and it is called verification. And halting problem has nothing to do with compile time overflow detection. Even if program may not (or intentionally is not supposed to) halt at all it can be still proven to not to cause overflow ever (Cthulhu loop would be an example of such program). Though it is not an easy tasks for any non-trivial programs and may require writing them in certain way. – user7860670 Sep 19 '17 at 12:21
  • 1
    @KlasLindbäck That's a incorrect assumption. C and C++ isn't a beautified assembly language. When you incur UB, the compiler might compile your code into something absolutely different than what you expect. Knowing hardware details won't help, you'd have to know the compiler inside out. – Passer By Sep 19 '17 at 12:21
  • @MSalters So it's possible for the processor to not even set the flags in case of an overflow? –  Sep 19 '17 at 12:23
  • @JenniferAnderson __YES__, [check this out](https://godbolt.org/g/sWkxjb) – Passer By Sep 19 '17 at 12:23
  • @JenniferAnderson Unsigned arithmetic is defined as modulo arithmetic. There are no UB with "overflowing" them. – Passer By Sep 19 '17 at 12:25
  • Overflow is not unversally bad. I use byte wrap to implement [256] circular buffers. – Martin James Sep 19 '17 at 12:27
  • @PasserBy I understand that with signed overflow the behavior is not determined by the standard but I think that most people would agree that overflow can happen also when we use unsigned variables and even if the behavior is defined by the standard this does not mean that it is not possible to cause bugs in the program or that the behavior is mostly unwanted when it happens, just like the signed overflow. –  Sep 19 '17 at 12:29
  • It is certainly possible, other languages do it, but not popular in a language like C. Intel processors have a dedicated instruction for it, `INTO`, but it takes a byte and costs 4 cycles. Never once seen it used, it did get a bad start because its underlying interrupt vector was already used on PCs. And solves only half the problem, integer promotion requires also checking that there is no overflow when the result needs to be hammered back into a variable. There are safeint libraries around to opt-in explicitly. – Hans Passant Sep 19 '17 at 12:29
  • @MartinJames I know it can be used for many practical purposes. However I am talking about those cases where overflow is just an error, an unwanted behavior of the program, a logical bug, whose possibility went undetected during development. –  Sep 19 '17 at 12:30
  • @PeterJ_01 That makes the question unclear. Looks like some fundamental missconception about compilation. – too honest for this site Sep 19 '17 at 12:44
  • @PasserBy There is nothing wrong with my argument. Note that I didn't make *any* assumption about UB for platform-specific code. You would have to turn to the platform-specific docs to see if there is defined behaviour for any/each case that is specified as UB by the standard. Your last sentence about knowing the compiler is spot on. – Klas Lindbäck Sep 19 '17 at 12:45
  • @Martin James This is wraparound not the overflow. overflow != wraparound. – 0___________ Sep 19 '17 at 12:50
  • @PeterJ_01 In C it is most likely none of both, but conversion or masking. – too honest for this site Sep 19 '17 at 12:51
  • @PeterJ_01 What is the difference between WrapAround and Overflow. I searched on the internet and I found a definition that sounds like overflow to me. I never heard the term wraparound used in the context of overflow or programming until now so I am confused. –  Sep 19 '17 at 12:53

2 Answers2

6

It is impossible to detect and prevent overflow at compile time in the general case. There as specific circumstances where obvious overflows can be detected at compile time, such as those occurring during constant expression evaluation, and compilers usually report such problems.

Note that overflow is a problem for signed arithmetic in C. Unsigned arithmetic is performed modulo the power of 2 one past the maximum value of the promoted type.

What compilers do is assume that signed arithmetic performed as coded by the programmer will not overflow and optimize the code based on this assumption. For example the following test can be omitted by aggressive optimizers:

int test(int x) {
    if (x + 1 > x) {
        /* this is not a way to test for potential wrap-around
         * since overflow is UB, the compiler can assume that incrementing
         * an int always evaluates to a larger int.
         */
        return x + 1;
    }
    return 0;
}

Detecting overflow at runtime is not specified in the C Standard. Code generators can add instructions for this purpose at a relatively low overhead to perform specific overflow handling. Other languages do this, but many C developers are reluctant to have even the smallest overhead for something they wrongly assume to never happen. It is useful to have this as a debug mode, and modern gcc and clang compilers provide sanitize options for address checking and other problems. For example you should check -fsanitize=undefined:

For unsigned overflow, runtime detection would be possible via extra generated code that checks the processor flags, but since the behavior is defined, the sanitization options seem to not care about this type of overflow.

A different approach may be more appropriate for your purpose: gcc provides built-in functions to perform signed and unsigned arithmetic and report overflow at runtime:

chqrlie
  • 131,814
  • 10
  • 121
  • 189
0

Answering the second part of the question only:

Some compilers have special builtins to detect overflows. Usually it adds a massive overhead and your integer calculations will execute much much slower but faster than C code doing the same checks. https://gcc.gnu.org/onlinedocs/gcc-7.1.0/gcc/Integer-Overflow-Builtins.html

Community
  • 1
  • 1
0___________
  • 60,014
  • 4
  • 34
  • 74