4 ms·
What a stupid "smart" compiler.
by titzer 4y ago
What a stupid "smart" compiler.
- Gibbon1 4y agoI think it's the optimization the compiler writers insist on that developers absolutely do not want. When the compiler detects UB any code that depends on it can be 'safely' deleted. It's the sort of arrogant attitude that's behind driving people away from C/C++
- logicchains 4y agoIt's absolutely an optimisation that people trying to achieve maximum performance from C/C++ expect. It's impossible to have the same degree of performance without such optimisations, hence why new language Zig has even more undefined behaviour than C.
- abainbridge 4y agoFrom the Zig language reference: Zig has many instances of undefined behavior. If undefined behavior is detected at compile-time, Zig emits a compile error and refuses to continue. Most undefined behavior that cannot be detected at compile-time can be detected at runtime. In these cases, Zig has safety checks. [...] When a safety check fails, Zig crashes with a stack trace
- Gibbon1 4y ago> Zig crashes with a stack trace I hope the people behind Zig understand that in critical applications that's totally unacceptable.
- kristoff_it 4y agoWhat exactly is the language supposed to do then. Let's say that you caused an integer overflow, or tried to perform an out of bounds access in a dynamic array. What's the program supposed to do if not crash. If your point is that some software shouldn't crash, then yes, for sure. But that's on you to not make programming errors in your code. In fact Zig does help you create software that doesn't crash like not many other programming languages do, for example by not having language features that rely on implicit memory allocations. This gives you the opportunity to always have a fallback strategy if a memory allocation fails.
- AndyKelley 4y agoIt seems that the semantics of undefined behavior are elusive to many people in the industry, so allow me to clarify some misconceptions. 1. Zig does not have more undefined behavior than C. Much like there are two kinds of complexity, accidental, and essential, C has multiple kinds of undefined behavior: accidental, and essential. Accidental UB is stupid shit like "if your file doesn't end with a newline, UB occurs". Essential UB is things like, if the memory of a local variable is changed by /proc/mem by another process, while a function is evaluated, UB occurs. Essential UB allows basic, essential optimisations to take place that everyone expects every language & compiler to be able to perform. C has a large amount of accidental UB; Zig has none. 2. A Zig application decides what to do when a safety check triggers by overriding the panic handler. Zig's default panic handler crashes with a helpful stack trace. This is a killer feature. 3. I see a lot of people talking ignorantly about safety critical applications. Let's talk about Level A Clearance. This is software that is licensed to run on airplanes and other safety critical components in the United States. Here's how it works: you have to test every error condition and every branch at the machine code layer. This makes a simpler language such as C or Zig more well-suited than language with hidden control flow such as C++ or Rust, because it causes problems for testing every branch at the machine code level. Furthermore, such components are redundant, so that when one fails, the readings of the others are used. So, crashing or otherwise indicating a faulty reading is absolutely what you want safety-critical software to do, as opposed to giving a well-defined, incorrect reading due to, for example, an integer overflow, which can happen in "safe" Rust.
- pjmlp 4y agoWhat is driving people away from C and C++ are the CVE's that keep being the same for the last 40 years, despite everyone repeating that one only needs to be good enough developer and use the tools to avoid them. The abuse of UB is the way how those 1980's C and C++ compilers that generated lousy code easly outperformed by Assembly coders on 8 and 16 bit home computers, finally improved their code generation quality due to the lack of strong type information for the compiler. So where we are, trying to escape bad decisions from the past.
- foota 4y agoThis is a misunderstanding of how compilers work. Compilers don't actively go out of their way to erase code that it thinks should be skipped, but rather as a consequence of multiple optimizations, code may end up being compiled differently than intended. void Foo(Bar * bar) { if (bar == nullptr) { println("Bar is null!"); } return bar->ComputeFoo(); } E.g., one pass may say "the println code is unreachable unless a null pointer is dereferenced", and the next may say "the only code that is reachable is `return bar->ComputeFoo()`", so just compile the function as that. Imagine instead of a println the code is actually some large body of code, and that the function is inlined into another where bar is null. In that case you'd want the compiler to avoid compiling the code, but it can't without those passes.
- pjmlp 4y agoCompilers for languages like Ada or Eiffel will usually disregard optimization algorithms that might go into "this might crash your airplane" kind of territory, whereas in C and C++ land whatever, as long as we get a few more μs, who cares.
- titzer 4y agoIndeed, the mindset is the key issue. In JVM land, where I learned most of my compiler ideas, the assumption is "optimization is not observable". JVMs move heaven and earth to make it appear as if they were simple interpreters just running the bytecodes one by one. The C/C++ world is the only one I can think of where this is manifestly not the case: optimizations are routinely observable and an endless source of confusion and frustration for developers. In the presence of even a single bug in the application, suddenly UB results in the veritable gates of hell opening and the entire lower world of the guts of abstractions comes spilling out. Woe to those who would try to debug at this level, for they fight demons of every form.
- samus 4y agoThere are two target groups for a C/C++ compiler: 1) embedded or OS hackers: they want code generation to be predictable and dislike surprising optimizations. To them, undefined behavior is behavior outside the standard specific to certain compilers that they expect to not suddenly change. 2) application and especially HPC developers. They want the compiler to exploit every trick in the literature to improve performance. In return, they are aware that undefined behavior cannot be relied on. Any compiler that is popular with both crowds would have to strike a compromise.