6 ms·
But it might not be undefined behaviour at compile-time. Consider if instead of just 'f(nullptr)', the call in the main() function had been 'f(getchar() == 'x'
by Athas 9y ago
But it might not be undefined behaviour at compile-time. Consider if instead of just 'f(nullptr)', the call in the main() function had been 'f(getchar() == 'x' ? nullptr : &x)' (where x is some variable in scope). It cannot be known until run-time whether a NULL pointer is being dereferenced, but since the pointer inside of 'f()' is being dereferenced, the compiler can assume that it will not be NULL.
- ladberg 9y agoSorry, I was referring to the program as a whole. I get why it did the optimization for that one function in particular, but in this case, it can be proven that the function call will result in undefined behavior and (in my opinion, not necessarily the way the C standard works) it should be flagged or not compiled.
- jhasse 9y ago> it should be flagged or not compiled. It will be, if you use clang-tidy (or clang's static analyzer): $ clang-tidy main.cpp -- -std=c++14 1 warning generated. main.cpp:10:5: warning: Forming reference to null pointer [clang-analyzer-core.NonNullParamChecker] f_unused_parameter(*i); ^ main.cpp:19:7: note: Passing null pointer value via 1st parameter 'i' f(nullptr); ^ main.cpp:19:5: note: Calling 'f' f(nullptr); ^ main.cpp:10:5: note: Forming reference to null pointer f_unused_parameter(*i); ^
- cesarb 9y agoDo not put your faith in whole program optimization. If it can be proven that the function call will result in undefined behavior, the compiler will assume that the function will never be called. If it can be proven that it will always be called, the compiler is free to assume that the program will never be run, and optimize the whole program down to nothing. That is, undefined behavior propagates not only forwards (if you dereference a pointer, from them on you can be sure that it's not null), but also backwards (if you dereference a null pointer, that's a contradiction since null pointers can't be dereferenced, and the contradiction can only be resolved if the statement is unreachable).
- oconnor663 9y ago> If it can be proven that it will always be called, the compiler is free to assume that the program will never be run, and optimize the whole program down to nothing. Does that happen when the compiler assumes you'll never take branches that lead to UB, and then finds a path through your branches that more or less does nothing? Or can it happen even if you're not branching at all? Also, say my program is int main() { printf("hello world\n"); do_some_UB(); } Is the compiler really allowed to produce a program that doesn't print?
- Joky 9y agoYes the compiler can remove the printf.
- masklinn 9y ago> Does that happen when the compiler assumes you'll never take branches that lead to UB, and then finds a path through your branches that more or less does nothing? Or can it happen even if you're not branching at all? Yes and yes. How far it will propagate these backwards depends on the compiler. > Is the compiler really allowed to produce a program that doesn't print? Yes. A program which contains UB is illegal, there are no guarantees about any of its behaviour, including behaviour which precedes any possible actual invocation of UB, this is pointed rather clearly by the standard: > However, if any such execution contains an undefined operation, this International Standard places no requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation).
- oconnor663 9y agoGood heavens! :)
- jsteemann 9y agoPotentially unsafe optimizations, undefined behavior and random crashes that are hard to reproduce are normally nothing one wants to have in production builds. It's nice that UBSan will detect the problem at runtime, but that requires one to actually use UBSan in development and have all relevant code paths triggered in a UBSan-instrumented build. Which is unrealistic at least when 3rd party code (libraries etc.) comes into play that is not entirely under the application's control. So I would really favor optimizations that do not make a program less safe, or are only applied when can be proven that they do not cause any harm.
- lallysingh 9y ago3rd party code is either in source form, that you can use with UBSan (via invocation from your own code's tests), or already in binary form, where compiler optimizations have already occurred and are now just flat out bugs in their build.