link to my UB post
[web.git] / personal / _posts / 2019-07-14-uninit.md
index dd71945750070c242bda06954a8f858db03a28d5..c8f2d9da050f2222bb813f9442cfa605d4e769c0 100644 (file)
@@ -57,7 +57,7 @@ How is this possible?
 The answer is that, in the "abstract machine" that is used to specify the behavior of our program, every byte in memory cannot just have a value in `0..256` (this is Rust/Ruby syntax for a left-inclusive right-exclusive range), it can also be "uninitialized".
 Memory *remembers* if you initialized it.
 The `x` that is passed to `always_return_true` is *not* the 8-bit representation of some number, it is an uninitialized byte.
 The answer is that, in the "abstract machine" that is used to specify the behavior of our program, every byte in memory cannot just have a value in `0..256` (this is Rust/Ruby syntax for a left-inclusive right-exclusive range), it can also be "uninitialized".
 Memory *remembers* if you initialized it.
 The `x` that is passed to `always_return_true` is *not* the 8-bit representation of some number, it is an uninitialized byte.
-Performing operations such as comparison on uninitialized bytes is undefined behavior.
+Performing operations such as comparison on uninitialized bytes is [undefined behavior]({% post_url 2017-07-14-undefined-behavior %}).
 As a consequence, our program has undefined behavior, so we should not be surprised that it acts "weirdly".
 
 Of course, there is a reason for this undefined behavior.
 As a consequence, our program has undefined behavior, so we should not be surprised that it acts "weirdly".
 
 Of course, there is a reason for this undefined behavior.
@@ -121,9 +121,9 @@ But when writing Rust programs, even when writing Rust programs that you only in
 The Rust abstract machine *does* make a distinction between "relaxed" and "release"/"acquire", and your program will go wrong if you ignore that fact.
 After all, x86 does not have "uninitialized bytes" either, and still our example program above went wrong.
 
 The Rust abstract machine *does* make a distinction between "relaxed" and "release"/"acquire", and your program will go wrong if you ignore that fact.
 After all, x86 does not have "uninitialized bytes" either, and still our example program above went wrong.
 
-Of course, desirable optimizations explain *why* the abstract machine is defined the way it is.
+Of course, to explain *why* the abstract machine is defined the way it is, we have to look at optimizations and hardware-level concerns.
 But without an abstract machine, it is very hard to ensure that all the optimizations a compiler performs are consistent---in fact, both [LLVM](https://bugs.llvm.org/show_bug.cgi?id=35229) and [GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65752) suffer from miscompilations caused by combining optimizations that all seem fine in isolation, but together cause incorrect code generation.
 But without an abstract machine, it is very hard to ensure that all the optimizations a compiler performs are consistent---in fact, both [LLVM](https://bugs.llvm.org/show_bug.cgi?id=35229) and [GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65752) suffer from miscompilations caused by combining optimizations that all seem fine in isolation, but together cause incorrect code generation.
-The abstract machine is the ultimate arbiter that shows if all of the optimizations are correct, or if some of them are in conflict with each other.
+The abstract machine is needed as an ultimate arbiter that shows if all of the optimizations are correct, or if some of them are in conflict with each other.
 I also think that when writing unsafe code, it is much easier to keep in your head a fixed abstract machine as opposed to a set of optimizations that might change any time, and might or might not be applied in any order.
 
 Unfortunately, in my opinion not enough of the discussion around undefined behavior in Rust/C/C++ is focused on what concretely the "abstract machine" of these languages looks like.
 I also think that when writing unsafe code, it is much easier to keep in your head a fixed abstract machine as opposed to a set of optimizations that might change any time, and might or might not be applied in any order.
 
 Unfortunately, in my opinion not enough of the discussion around undefined behavior in Rust/C/C++ is focused on what concretely the "abstract machine" of these languages looks like.