6 ms·
I 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_capacit
by reza_n 9y ago
I 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.
- reza_n 9y ago> But it certainly can change the condition in the assertion so that it won't fire on overflow. Once again, why would a compiler do that? To satisfy the Rust community's desire to spread FUD throughout the C community? (sorry to be so blunt, but im really scratching my head here) A more logical thought process here is that signed operations aren't uniform across architectures and are sometimes emulated, leading to UB for certain edge cases, like overflow. Its more practical to believe that a future C standard will fix this loophole rather than think compilers will exploit this and punish their own community. Very not impressed with this thread.
- nkurz 9y agowhy would a compiler do that? The theory is that constraint propagation enables optimizations that aren't possible otherwise. In particular, it lets the compiler avoid emitting code for conditions it judges are impossible to occur. This usually doesn't help much with C, but can be useful with C++, and many of the optimization decisions are driven by C++ performance. To satisfy the Rust community's desire to spread FUD throughout the C community? I'm a big fan of C, and consider it my primary language. I have barely used Rust and am not part of the Rust community. A more logical thought process here is that signed operations aren't uniform across architectures and are sometimes emulated, leading to UB for certain edge cases, like overflow. Personally, I would love if this was the vision for C that compiler writers held. But it is not, and has not been for at least a decade. Its more practical to believe that a future C standard will fix this loophole rather than think compilers will exploit this and punish their own community. Unfortunately there is no chance that this will happen. That ship has sailed. Compilers are taking ever greater advantage of undefined behavior for purposes of optimization. Overflowing a signed integer is undefined behavior, therefor real-world compilers can and do strip out checks that they determine would require undefined behavior to be occur. I realize this is hard to believe, but try this article as an intro: https://blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p=633 https://blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p=... Or even better, just look at the assembly that is generated here: #include <assert.h> int add_one(int num) { int increased = num + 1; assert(increased > num); return increased; } Both GCC and Clang completely remove the assert from the generated code: https://godbolt.org/g/5k43pV https://godbolt.org/g/5k43pV. To confirm, try adding "unsigned" to the "int" declarations and notice that it then keeps the check. I don't think either removes the check yet in the exact multiply by two case that you offer, but it is not safe to depend on this behavior. Very not impressed with this thread. I can see why you feel that way, but I think if you research this further you'll come to appreciate the stern warnings that people are giving you in this thread. C does not work the you want it to. Your choices are to adapt and avoid undefined behavior, or switch to a better language. I'm sticking with C because I think it's the best choice for what I do, but you need to be aware of the dangers if you are going to use it.
- amluto 9y ago> Your choices are to adapt and avoid undefined behavior, or switch to a better language. Sadly, a lot of people choose the third choice: write code in what they imagine C to be, fiddle with it until it compiles without warnings and, if they're trying extra hard, passes limited testing with Valgrind. Then they ship it.
- dpc_pw 9y agoOh. In case you wanted to assert the capacity = 0 isn't happening, it's OK. I was talking about overflow protection. I'm sorry if I've missed something you said that was implying that. If you wanted to check overflow condition, this assert doesn't help. If the capacity was almost MAX_INT, and you multiply it be 2, then compiler has freedom to do whatever, and not catch it because it must never be happening in the first place.