5 ms·
Once again, I want to plead. At least have a Warning option to annotate any time undefined behavior is encountered by a compiler. The goal should be to promot
by mjevans 3y ago
Once again, I want to plead. At least have a Warning option to annotate any time undefined behavior is encountered by a compiler. The goal should be to promote optimizations to written code and improve code quality. Not just the result of one particular compiler.
- layer8 3y agoUndefined behavior are runtime conditions, in the general case, not compile-time conditions.
- wrs 3y agoEliminating a statement by assuming UB will never happen is a compile-time condition. I think the problem is more that it’s not as if there’s a single place in the compiler saying “aha! UB! let’s surprise the developer!”. It’s the effect of propagation through multiple optimization steps.
- layer8 3y agoNot quite, it’s the fact that if you have to assume the UB condition and make behavior defined for that condition, then you can’t apply certain optimizations, and/or you have to generate extra code to detect and handle the UB condition. In any case, it would mean that existing programs that do not exhibit UB (but that contain expressions that could be UB when executed in the context of a different program) would suddenly compile to less efficient code. It’s not surprising that compiler vendors have little interest in agreeing to such changes to the C standard, which effectively would mean a performance regression for their compilers. You can’t change the situation without either forfeiting some performance or changing existing programs. This is how UB came about in the first place, in the first ANSI C version. Everything the compiler vendors couldn’t agree on to specify even just an implementation-defined behavior for, became UB.
- nlewycky 3y agoHi! I'm a former compiler engineer who specialized on undefined behaviour. Would you like warnings on: * int f(int x, int y) { return x + y; } * int get_x_coord(Point *p) { return p->x; } * void compute_and_cache(const char *key) { *get_cache_bucket_for(key) = compute_value_for(key); } I'm curious, what would you do with a warning on every load or store through a pointer? On the flip side, I can offer -fsanitize=undefined which will catch when you do many things that have UB at runtime. It does not change the ABI which means that there are some bugs it can't catch, but deploying it is easier since you do not need to recompile all your libraries with it (like your C++ standard library and C library, in particular). You can use this to help you build unit tests that send intentionally overflowing values into your functions and show that they do not overflow. It turns untestable problem (since you cannot check for UB after it happens) into a problem you can write deterministic tests for.
- wrs 3y agoThe problem isn’t overflow, the problem is the backwards logic of the compiler assuming there will never be any execution that leads to overflow, so the code that overflows just vanishes completely. In other words, bool overflowed = (x+1)<x; should be meaningful. It may or may not do what you want on any given architecture, but it shouldn’t just be assumed false.
- dzaima 3y agoHow about if the x+1 was from an inlined function? a macro? perhaps even just a variable defined 10 lines up? In a 7-character sequence it may seem pretty obvious that it's probably intended to mean something, but when joining together multiple independent things doing redundant operations it's much less trivial. int game_logic(int prev_score, int bonus) { if (bonus < 0) { // check for bad argument return -1; } int new_score = prev_score + bonus; // ... if (new_score < prev_score) { // sanity check abort(); } return new_score; } // in the above the abort path can (and is) already optimized out, but an invocation of game_logic(x,1) becomes exactly x+1<x
- zzo38computer 3y ago
- pornel 3y agoUB is not an event that happens. It’s an assumption baked into the design of the compiler. For example, on 64-bit arch if you index arrays by an int, compiler can use CPU’s 64-bit addressing modes even when they don’t overflow when 32-bit int would. The compiler is taking advantage of it all the time. It wouldn’t make sense to warn about every array, but OTOH the compiler can’t know at compile time if your pointer arithmetic will ever overflow an int.