5 ms·
Hm… so Rust compiles code as is, whereas C “overly smart” compiler mangles correct code into faster, less correct version. If Rust is too slow (as measured by
by tomp 5y ago
Hm… so Rust compiles code as is, whereas C “overly smart” compiler mangles correct code into faster, less correct version.
If Rust is too slow (as measured by the profiler… premature optimisation etc.), you can always take another look at the algorithm and optimise it manually, and correctly.
On the other hand, if C is wrong… let’s hope you manage to isolate the fault to this function (a big if!)… start up the debugger… the assembly will likely look correct, because the compiler won’t optimise so aggressively in a debug build! Good luck debugging <3
- secondcoming 5y agoIf your code has UB then it was never correct. The issue is that instead of telling you about your UB, compiler writers use it to generate very quick but broken programs
- MichaelBurge 5y agoSuppose there are 3 translation units compiled from: a.c int foo(int* ptr); int main() { return foo(0); } b.c int foo(int* ptr) { return *ptr; } c.c int foo(int* ptr) { return 5; } All three translation units do not have undefined behavior, so no compiler should report it. At the time of compilation of a.c, foo does not have a definition. If it is linked with b.c's object file, the program would have undefined behavior. But if it is linked with c.c's object file, there is no undefined behavior. Object files can't tell who they're going to be linked with. And when b.c is compiled, foo only exhibits undefined behavior if somebody else calls it with an invalid pointer. It's not b.c's problem. Further, a.c and b.c might be compiled with different C compilers(very common), so you can't rely on any kind of caching of type information or state-tracking across translation units. When the linker is run, the undefined behavior is instantiated to create an incorrect binary, but linkers aren't regulated by the C standard so it wouldn't be appropriate to include a UB checker in one. To do what you're saying, you'd need a language designed for whole-program analysis. Rust and Haskell do this, and they both require you to have source code for all your dependencies so they can recompile them each time. It'd be quite the design change for C, and not something compiler writers can "fix" by themselves.
- anonymoushn 5y agoIt sounds like we should solve the issue by never using dynamic linking
- scoutt 5y agoWhat OP said has no thing to do with dynamic linking. OP is talking about the linker; the thing that generates the binary by stitching together all the compiled code.
- deleted 5y ago[deleted]
- imtringued 5y agoYes but dynamic linking causes unexpected changes at runtime of the program. Undefined behavior often happens at runtime, so an update of a library can cause undefined behavior in your application. The only way a sufficiently skilled developer can avoid undefined behavior is by checking for undefined behavior at runtime. We are now back to the reason why undefined behavior exists: because we wanted to avoid runtime checking. The idea that you can just stop writing code with undefined behavior is absurd.
- scoutt 5y ago> The idea that you can just stop writing code with undefined behavior is absurd. If this is true, then this should also apply to Rust or other proven languages: your program will still run in a dynamic environment, and probably calling into all kind of OS and third party libraries. Unless... you write your own (unsafe) wrappers around libraries, trying to catch, as much as possible, errors that can filter into the Rust (or whatever) code. But still, someone has to write these wrappers. If it's not you, you have to trust on somebody else's work, and this is a runtime check that will slow your program down.
- MichaelBurge 5y ago
- kzrdude 5y agoWhen you write it like that, it sounds insane. But it's very far from how compilers work. There is nothing like "find UB, then take advantage of it", it's completely inverted. The normal rules the optimizer works from assume there is no UB. It's just always the normal rules, and they work the same way for all programs. MichaelBurge's comment has illustrated this better than I could.
- fooker 5y agoYou could use appropriate tools like valgrind and compile with ubsan to make this a non-issue. So I'd happily take more performance for code without UB trading off slight inconveniences for debugging UB issues.