4 ms·
Overflow is a runtime behavior, not a compile time behavior. How a type overflows is dependent on the CPU, not software.
by reza_n 9y ago
Overflow is a runtime behavior, not a compile time behavior. How a type overflows is dependent on the CPU, not software.
- koopa184 9y agoThe C standard explicitly lists signed integer overflow as an undefined behavior. Any undefined behavior in your program essentially makes it semantically meaningless. There is no guarantee that the compiler will even emit the assembly instructions that would lead to signed overflow behavior. It could just as well emit a program that deletes your files, and still be standards-compliant.
- nkurz 9y agoYou are either trolling or dangerously wrong. A modern optimizing compiler will simply remove your assert() from the generated assembly. If you are trolling, stop it. But if you are a C programmer and speaking honestly, you need to have a better understanding of undefined behavior in C before you write any more code. Checking for signed overflow in C is extremely difficult to do correctly. This is a good starting point: https://blog.regehr.org/archives/213 https://blog.regehr.org/archives/213.
- reza_n 9y agoNothing in the snippet is undefined. The assert simply enforces the size always increases. Not sure I understand why you think the assert() gets removed. Is this documented somewhere? Hint: vec->capacity could be 0
- dpc_pw 9y agoAFAIK you are wrong, and the other poster is right. Signed overflow (in int * 2) is an UB. If it happens, compiler is free to do anything. Eg. assume your assert can never happen and remove it. Let me explain: Because signed overflow is an UB, compiler assumes that you would never write a code that overflows like that (because you write C, the assupmtion is that you are omnipotent), and knowing that, remove the assert that could possibly never ever happen, since it's a dead code anyway. I've spend more than 6 years writting embedded software in C. God I love Rust.
- reza_n 9y agoHow does a compiler know that signed overflow will happen in the above snippet? Couldn't all integer math result in overflow? If so, how does the compiler ever know what to do? I do not think its plausible that the compiler is emitting code which checks for an overflow and then in a deterministic fashion skips all dependent logic there after. Im sorry, but I think this line of argument has been taken to such an extreme it has detached from reality.
- amluto 9y agoThe compiler will see that you calculated capacity * 2. Since overflow is UB, the compiler may under that any code path that does this calculation does not cause signed overflow and can deduce that capacity * 2 does not overflow. Therefore, for example, the condition that capacity * 2 > capacity is equivalent to capacity > 0, and there goes your assertion. A modern compiler will likely also deduce that capacity > 0 and remove the assertion entirely. You can read up on "value range propagation" if you're interested. But all this is beside the point. In C, you may not invoke undefined behavior and then expect anything at all about the result. With malicious input, UB can and will result in RCE.
- reza_n 9y agoI can see the point you are trying to make, but in this context, it doesn't work. Lets start at line 20: vec.capacity = 0; Next, line 26: int new_capacity = vec->capacity * 2; So we get new_capacity = 0 * 2, so new_capacity is 0. The assert: assert(new_capacity > vec->capacity); Which translates to 0 > 0, it triggers a fail and we are done. If the compiler were to 'optimize' that out, then the compiler just introduced a very serious and fatal bug in our program, and we didn't even overflow or UB. So that assert works as intended, it forces new_capacity to grow until it hits INT_MAX or UB, at which point it will assert.
- amluto 9y ago> I can see the point you are trying to make, but in this context, it doesn't work. No, you don't see the point. Writing code in C that invokes undefined behavior is wrong, full stop. You seem to think that it's only wrong if you, the programmer, can imagine how it would go wrong. > If the compiler were to 'optimize' that out, then the compiler just introduced a very serious and fatal bug in our program, and we didn't even overflow or UB. Sure, in this case, the compiler can't optimize the assertion out. But it certainly can change the condition in the assertion so that it won't fire on overflow.