
CppCon 2016: Chandler Carruth “Garbage In, Garbage Out: Arguing about Undefined Behavior..."
About this video
Chandler Carruth's CppCon 2016 talk tries to defuse the heated debate over undefined behavior in C and C++. He explains from the compiler writer's perspective why UB exists and how it enables optimization.
Why it appears in the archive
HN points to it whenever undefined behavior comes up, as the best explanation of the reasoning behind UB, though some dispute its framing.
AI-generated summary and labels from the source dataset; verify important details against the video. Source & credits.
From the Hacker News discussion
The generally recommended thing for catching & fixing this is: [LINK] CppCon has also had a lot of great talks on UB and why it is what it is, such as [VIDEO]
Read original comment ↗Chandler Carruth's talk on the subject was really useful for my own understanding of the reasoning behind UB: [VIDEO]
Read original comment ↗Actually I discourage my colleague to use unsigned especially because they can overflow. The problem with overflow is that most of the time it is a program bug if there is an overflow that wasn't intended. Using signed arithmetic means that you can actually trap on overflow and catch these bugs (using fuzzing for instance). Chandler explained it nicely in his CPPCon 2016 talk "Garbage In, Garbage Out: Arguing about Undefined Behavior...". I encourage to watch the full talk but here is one relevant example: [VIDEO] And here he mentions how Google experimented with this internally: [VIDEO]
Read original comment ↗One man's "broken code produced by the compiler" is another man's "excellently optimized code by the compiler". Where to draw the line is not always clear, but here's a very clear-cut example[1] where emitting a warning would be bad. If you don't want to watch the video, it's basically this: - the code technically contains undefined behavior, but it will never be actually triggered by the program - changing the code to remove undefined behavior forces the compiler to emit terrible code Making the compiler yell at the programmer in this case would be terrible, but it's clearly a consequence of what you're asking. [1] [VIDEO]
Read original comment ↗I very much doubt it, as it goes against the C culture of micro-optimize each code line as it is written, without any feedback from a profiler because "the coder knows best!". Since I know C (1992), I have seen quite a few times people write code to go fast as they can and apply compiler optimization tricks for use cases where it hardly matters. Also many of the issues regarding UB go back to the early ANSI C days, when it was the wild west of C dialects outside UNIX and no vendor wanted to give up on their own extensions. As for C and C++ compiler writers view on UB: [VIDEO]
Read original comment ↗I haven't actually watched it in a while, but are you referencing this talk by Chandler Carruth? [VIDEO]
Read original comment ↗Signed integer overflow causing undefined behaviour allows the compiler to make significantly better optimisations. Here is Chandler Carruth, and clang developer, talking about it: [VIDEO]
Read original comment ↗It's not obvious unless you read and think about the assembly, but bonzini's point was that using a 32 bit signed int (which is not allowed to overflow) means the compiler can cleverly promote it to use register RAX as an index without any other shenanigans to deal with 32 bit overflow. RAX is a 64 bit register for integers or pointers. There are reasons why this might be advantageous over using EAX, which is the name for the low 32 bits of RAX. It's very possible that bonzini is referring to the example in the following link: [VIDEO] Back to your overall point though, you're right that there's frequently an advantage to having your bulk data use smaller data types. It's better for caching and memory bandwidth, and it opens up more possibilities for parallelization with SIMD or GPU magic. However, it's really a false economy for things like loop indices. It doesn't matter if you declare your variable to be int8_t using just 1 byte, because it's probably going to tie up an entire 64 bit register anyways. There are ways to use only parts of registers, so you can pretend you have more registers, but these cause dependency stalls and are generally not good for modern processors, or at least not a win for speed. To a lesser extent, it's a false economy with floating point on the CPU too. Your 32 bit float is likely taking up an entire 128 bit (or larger) SIMD register, and the operations generally have the same latency and throughput as their 64 bit (double) equivalent. The rules
Read original comment ↗