Hacker News new | ask | show | jobs
by googh 618 days ago
I just wrote that as an observation, and I did not mean to offend the parent.

Now, let me explain why I felt that way. First and foremost, the phrase "undefined behavior" only applies to C and C++ because the specifications of those languages define it. The statement that Rust has no UB does not make sense because Rust has no specification, and all behavior is defined by the default implementation.

For example, C/C++ specifications state that using a pointer after calling "free()" on it is UB. But an implementation can make it well-defined by adding a GC and making "free()" a no-op. Hence, memory safety is entirely orthogonal to UB.

Another example: signed overflow being UB is not a memory safety problem unless the value is used for array indexing. Also, it is possible to enable bounds checking in STL containers (like _GLIBCXX_ASSERTIONS).

It seems like that a lot of Rust fans read John Regehr's posts and use "undefined behavior" as a boogeyman to throw shade at C/C++. They repeat the same points ad nauseam. It also helps that the phrase "undefined behavior" evokes strong emotions (eg., "nasal demons"). I see the parent commenter doing this frequently and sometimes[1] even in the C++ subreddit (of all the places!). How is this not obnoxious?

Here[2] is another person doing the same, but in a spicier tone. Linked lists and graphs are safe if you have an isoheap allocator (look at Fil-C).

You can say that it is moral to endlessly reiterate the problems of unsafe languages, because it could lead to more secure software. But see the reply to my other comment by "hyperbrainer"[3] which says that Rust is "completely" memory safe, which is entirely wrong[4]. It is hard not to suspect the motives of those who claim to be concerned about memory safety.

[1] -https://old.reddit.com/r/cpp/comments/1fu0y6n/when_a_backgro... [2] - https://news.ycombinator.com/item?id=32121622 [3] - I am unable to reply because of the depth. [4] - Rust requires unsafe to do a lot of things which can be done in safe code in a GC'd language. Thus, unsafe is pretty common in Rust than most GC'd languages. If a segfault can literally kill a person, it is absolutely immoral to choose Rust over Java (it does not matter that Rust "feels" safer than Java).

4 comments

I really am interested in what Safer C++ proposes for [1], but I never found out.

Your point [4] is very silly because you're assuming that while the unsafe code implementing a safe Rust interface might be flawed the code implementing a safe Java interface such as its garbage collector (which will often be C++) cannot be. As we'd expect, both these components are occasionally defective, having been made by error prone humans, such flaws are neither impossible nor common in either system. There are indeed even safer choices, and I've recommended them - but they're not Garbage Collected.

> First and foremost, the phrase "undefined behavior" only applies to C and C++ because the specifications of those languages define it.

Nope, those words have an ordinary meaning and are indeed used by Rust's own documentation, for example the Rustonomicon says at one point early on, "No matter what, Safe Rust can't cause Undefined Behavior". The purpose there is definitional, it's not a boast about how awesome Rust is, it's a claim that if there is Undefined Behaviour that's not because of the safe Rust, there's a soundness problem somewhere else.

> Another example: signed overflow being UB is not a memory safety problem unless the value is used for array indexing

This is wrong. Because Signed Overflow is UB the C++ compiler is allowed to just assume it will never happen, regardless of the systemic consequences. What that means is that other IR transformations will always be legal even if they wouldn't have been legal for any possible result of the overflow. This can and does destroy memory safety. Actually it would be weird if somehow the IR transformations always preserved memory safety, something they know nothing about, despite changing what the code does.

> The statement that Rust has no UB does not make sense because Rust has no specification, and all behavior is defined by the default implementation.

It is in the reference.

https://doc.rust-lang.org/reference/behavior-considered-unde...

> The statement that Rust has no UB does not make sense because Rust has no specification

I don't think it was claimed that Rust has no UB in this conversation, only IFNDR.

From what I can tell, Rust does document a set of "behavior considered undefined" like using unsafe to access misaligned pointers. For practical concerns ("could code optimization change these semantics?", "is this guaranteed to work the same on future compiler versions?") it seems reasonable to me to call that undefined behavior, and to say that Rust doesn't have much of it.

> I see the parent commenter doing this frequently and sometimes[1] even in the C++ subreddit (of all the places!). How is this not obnoxious?

Both their comment here and their reddit comment look fine to me. Something like "C++ sucks, switch to Rust!" would be annoying, but specific relevant technical comparisons ("In Rust for comparison the static growable array V isn't dropped when the main thread exits [...]") seem constructive.

> Rust requires unsafe to do a lot of things which can be done in safe code in a GC'd language. Thus, unsafe is pretty common in Rust than most GC'd languages. If a segfault can literally kill a person, it is absolutely immoral to choose Rust over Java (it does not matter that Rust "feels" safer than Java).

Java does technically have the Unsafe class for low-level unsafe operation and JNI to interoperate with C/C++/assembly.

I'd expect that the average Rust program makes more use of unsafe, but largely just because the average Rust program is lower-level (including, increasingly, parts of the Linux and Windows kernels). It's unclear to me whether the same program written in Java or Rust would ultimately prevent more bugs.

> Now, let me explain why I felt that way. First and foremost, the phrase "undefined behavior" only applies to C and C++ because the specifications of those languages define it. The statement that Rust has no UB does not make sense because Rust has no specification, and all behavior is defined by the default implementation.

There are at least three classes of definedness of behavior:

1. The behavior of a program is defined by a spec.

2. The behavior of a program is not formally defined by a spec, either because the language has no spec or because it's imprecise, but it's defined in a sociological sense: that is, if a compiler doesn't follow the apparent meaning of the program, the people who develop the compiler will consider it a bug and you can report it to mailing lists or GitHub and probably get support.

3. The behavior is definitely undefined: a compiler can do anything in response to the program and the developers of the compiler will not consider it a bug.

C++ has a lot of 1, comparatively not a lot of 2, and a lot of 3.

Rust has none of 1, a lot of 2, and a lot of 3. But safe Rust has very little of 3.