I think everyone would be less jaded if memory safety wasn’t hung over C/C++ people’s heads by certain communities and used as an existential threat to the language.
This is a bit like saying everyone would be a bit less jaded if the plane staying in the air wasn't hung over the Boeing 737 MAX 8 designer's heads by certain communities and used as an existential threat to the company.
Doesn't modern C++ offer the ability to write memory safe code? The primary distinguishing difference from Rust, on this front, is that Rust is memory safe by default (and allows them to override memory safety with code that is explicitly declared as unsafe) while C++ requires the developer to make a conscious effort to avoid unsafe code (without providing facilities to declare code as safe or unsafe). While this means that C++ is problematic, it does not make Rust automagically safer - particularly when interfacing with C/C++ code (as would be the case when interfacing with Linux syscalls or most C or C++ based libraries).
I guess what I'm saying is that Rust is great when dealing exclusively with Rust libraries since it is either memory safe by default or because it is easier to audit (since it is either declared explicitly or implicitly as unsafe). On the other hand, it is not guaranteed to be memory safe. While this may sound like nitpicking, the distinction is important from the perspective of the end user who is unlikely to ever audit the code yet may be swayed by being told that it is written in a memory safe language.
If you're writing C/C++ and you don't care about memory safety, you're taking one of a few possible positions:
1. "I don't care what my program does."
Why write it though?
2. "I don't care what the standard says, I've put text into a compiler and it gave me a binary that does the thing."
What if you want to put the same text into a different compiler in the future, or the same compiler again? Are you certain the binary is going to continue doing the thing? Have you even fully tested the binary?
3. "I use a special runtime that makes memory unsafety defined again."
One, I don't believe you unless you're part of a very small group of people and two, why are you accepting the serious drawbacks (performance, process death, all the broader issues of UB) that come with this?
It's genuinely hard for me to understand why you wouldn't think memory safety is important Don't you want to write code that's portable and correct? Don't you want to execute other people's programs and trust they won't segfault? Doesn't it frustrate you that the language committees have spent years refusing to address even the lowest-hanging fruit?
1. attempting to retcon garbage collected languages as not memory safe, or
2. discussing a particular implementation choice of the standard Go runtime that was made because it is not a practical source of bugs (see https://research.swtch.com/gorace, it is not an inherent feature of the language, just the implementation, and it is the right practical choice)
But either way: this is the sort of thing I have seen again and again in the Rust "community" that I find deeply off-putting. Build good things, do not play snooty word games.
If we're being extremely strict, Python probably also shouldn't be on that list because the CPython runtime is written in C and has had issues with memory safety in the past.
Ultimately, "memory safety" is a conversation about what a program is intended to do and what semantics the language guarantees that program will have when executed. For the vast majority of programs, you can be just as confident that your Go and Python code will do the right things at runtime as your safe Rust. It's good enough.
No, because then no language would be included, including Rust. Implementation bugs are not treated the same as integral parts of the language as defined by the standard. Python is defined as memory safe.
I understand this website as focusing on unsafety in a more practical sense of writing your stack in memory safe ways, not in the sense of discussing what's theoretically possible within the language specs. After all, Fil-C is standard compliant, but "run everything under Fil-C" is not the argument it's making. The most common language runtime being memory unsafe is absolutely an applicable argument here, mitigated only by the fact that it's a mature enough runtime that memory issues are vanishingly rare.
is go not memory safe? other than unsafe and other contrived goroutine scenarios, isn't it? I'm actually really curious - I've been writing go for just a couple years now and my understanding is the only ways for it to be unsafe are the two scenarios I described earlier.
When talking about the kind that lead to torn memory writes, no it doesn't have those. To share between threads you need to go through atomics or mutexes or other protection methods.
One of Rust's core guarantees is that a race condition in safe code will never cause UB. It might return a nondeterministic result, but that result will be safe and well-typed (for example, if it's a Vec, it will be a valid Vec that will behave as expected and, once you have a unique reference, is guaranteed not to change out from under you).
Usually people are talking about race conditions. When you say contrived you're thinking races conditions are difficult to win and unrealistic but attackers who have a lot of money on the line spend the time to win all sorts of wild race conditions consistently.
is there actually a programming language that makes race conditions impossible (I am not being facetious, I actually do not know)? if the existence of races makes a language unsafe, then aren't all languages unsafe?
It's not that race conditions are generally memory-unsafe. The same race conditions would not be memory-unsafe in, say, Java or Python.
Go has a memory model that basically guarantees that the language is memory-safe except with a few marked "unsafe" functions or in case of race conditions involving interfaces or arrays. It's pretty easy to come up with an example of such a race condition that will cause reads or writes from/to unpredictable memory addresses. I imagine it's quite feasible to turn this into reads or writes from/to crafted memory addresses, which would be a mean to defeat pretty much any security measure implemented in the language.
The Rust community caters to people who are a bit obsessive about safety (including myself) and Rust developers tend to consider this a bug in the design of the Go language (there are a few, albeit much harder to achieve, issues that are vaguely comparable in Rust and they are considered bugs in the current design of Rust). The Go community tends to attract people who are more interested in shipping than in guarantees, and Go developers who are aware of this issue tend not care and assume that this is never going to happen in practice (which may or may not be true, I haven't checked).
> is there actually a programming language that makes race conditions impossible
To my knowledge, no.
> if the existence of races makes a language unsafe, then aren't all languages unsafe?
Are we talking about "data races" or "race conditions" One can lead to the other, but race conditions are a much bigger set.
AIUI It's impossible for any language level controls to prevent any and all race conditions, because some are happening outside of the binary/process/computer.
Data races, OTOH are almost trivial to protect against - a contestable thing must have a guard that ensures a writer has exclusive access to that thing for the duration of the write.
Some languages do this with mutually exclusive locks (mutex/semaphore/go channels), some languages/paradigms do this by never having shareable objects (Functional Programming/Pass by Value), and some (Rust) are doing this with the compile time checks and firm rules on a single writer.
C and C++ as defined by their current standards are memory unsafe. You may argue that some specific implementations manage to stay as memory safe as they can get away with, but even then, features like union prevents a fully memory-safe implementation.
> C and C++ as defined by their current standards are memory unsafe.
I don’t think the spec says one way or another (but please correct me if you find verbiage indicating that the language must be memory unsafe).
It’s possible to make the whole language memory safe, including unions. It’s tricky, but possible.
Someone else mentioned Fil-C but Fil-C builds on a lot of prior art. The fact that C and C++ can be memory safe is no secret to those who understand language implementation.
By definition, C and C++ are memory safe as long as you follow the rules. The problem is that the rules cannot be automatically checked and in practice are the source of unenumerable issues from straight up bugs to subtle standards violations that trigger the optimizer to rewrite your code into what you didn’t intend.
But yes, fil-c is a huge improvement (afaik though it doesn’t solve the UB problem - it just guarantees you can’t have a memory safety issue as a result)
The mentions of curl on this website are misleading and/or outdated. Curl is dropping the rust/hyper backend. See https://daniel.haxx.se/blog/2024/12/21/dropping-hyper/
I think everyone would be less jaded if memory safety wasn’t hung over C/C++ people’s heads by certain communities and used as an existential threat to the language.
This is a bit like saying everyone would be a bit less jaded if the plane staying in the air wasn't hung over the Boeing 737 MAX 8 designer's heads by certain communities and used as an existential threat to the company.
Commenting from the sidelines:
Doesn't modern C++ offer the ability to write memory safe code? The primary distinguishing difference from Rust, on this front, is that Rust is memory safe by default (and allows them to override memory safety with code that is explicitly declared as unsafe) while C++ requires the developer to make a conscious effort to avoid unsafe code (without providing facilities to declare code as safe or unsafe). While this means that C++ is problematic, it does not make Rust automagically safer - particularly when interfacing with C/C++ code (as would be the case when interfacing with Linux syscalls or most C or C++ based libraries).
I guess what I'm saying is that Rust is great when dealing exclusively with Rust libraries since it is either memory safe by default or because it is easier to audit (since it is either declared explicitly or implicitly as unsafe). On the other hand, it is not guaranteed to be memory safe. While this may sound like nitpicking, the distinction is important from the perspective of the end user who is unlikely to ever audit the code yet may be swayed by being told that it is written in a memory safe language.
If you're writing C/C++ and you don't care about memory safety, you're taking one of a few possible positions:
1. "I don't care what my program does."
Why write it though?
2. "I don't care what the standard says, I've put text into a compiler and it gave me a binary that does the thing."
What if you want to put the same text into a different compiler in the future, or the same compiler again? Are you certain the binary is going to continue doing the thing? Have you even fully tested the binary?
3. "I use a special runtime that makes memory unsafety defined again."
One, I don't believe you unless you're part of a very small group of people and two, why are you accepting the serious drawbacks (performance, process death, all the broader issues of UB) that come with this?
It's genuinely hard for me to understand why you wouldn't think memory safety is important Don't you want to write code that's portable and correct? Don't you want to execute other people's programs and trust they won't segfault? Doesn't it frustrate you that the language committees have spent years refusing to address even the lowest-hanging fruit?
This site is curious in that in incorrectly categorizes go as memory safe.
Perhaps in part because the sponsors are invested in using go and benefit from its inclusion in a list of memory safe languages.
I am not sure if you are:
1. attempting to retcon garbage collected languages as not memory safe, or
2. discussing a particular implementation choice of the standard Go runtime that was made because it is not a practical source of bugs (see https://research.swtch.com/gorace, it is not an inherent feature of the language, just the implementation, and it is the right practical choice)
But either way: this is the sort of thing I have seen again and again in the Rust "community" that I find deeply off-putting. Build good things, do not play snooty word games.
If we're being extremely strict, Python probably also shouldn't be on that list because the CPython runtime is written in C and has had issues with memory safety in the past.
Ultimately, "memory safety" is a conversation about what a program is intended to do and what semantics the language guarantees that program will have when executed. For the vast majority of programs, you can be just as confident that your Go and Python code will do the right things at runtime as your safe Rust. It's good enough.
No, because then no language would be included, including Rust. Implementation bugs are not treated the same as integral parts of the language as defined by the standard. Python is defined as memory safe.
I understand this website as focusing on unsafety in a more practical sense of writing your stack in memory safe ways, not in the sense of discussing what's theoretically possible within the language specs. After all, Fil-C is standard compliant, but "run everything under Fil-C" is not the argument it's making. The most common language runtime being memory unsafe is absolutely an applicable argument here, mitigated only by the fact that it's a mature enough runtime that memory issues are vanishingly rare.
is go not memory safe? other than unsafe and other contrived goroutine scenarios, isn't it? I'm actually really curious - I've been writing go for just a couple years now and my understanding is the only ways for it to be unsafe are the two scenarios I described earlier.
Changes to multi-word pointers can cause UB due to race conditions in Go because only changes at the word level are atomic.
See: https://blog.stalkr.net/2015/04/golang-data-races-to-break-m...
Does Rust not have race conditions?
Rust prevents data races, but not race conditions.
When talking about the kind that lead to torn memory writes, no it doesn't have those. To share between threads you need to go through atomics or mutexes or other protection methods.
One of Rust's core guarantees is that a race condition in safe code will never cause UB. It might return a nondeterministic result, but that result will be safe and well-typed (for example, if it's a Vec, it will be a valid Vec that will behave as expected and, once you have a unique reference, is guaranteed not to change out from under you).
Usually people are talking about race conditions. When you say contrived you're thinking races conditions are difficult to win and unrealistic but attackers who have a lot of money on the line spend the time to win all sorts of wild race conditions consistently.
is there actually a programming language that makes race conditions impossible (I am not being facetious, I actually do not know)? if the existence of races makes a language unsafe, then aren't all languages unsafe?
It's not that race conditions are generally memory-unsafe. The same race conditions would not be memory-unsafe in, say, Java or Python.
Go has a memory model that basically guarantees that the language is memory-safe except with a few marked "unsafe" functions or in case of race conditions involving interfaces or arrays. It's pretty easy to come up with an example of such a race condition that will cause reads or writes from/to unpredictable memory addresses. I imagine it's quite feasible to turn this into reads or writes from/to crafted memory addresses, which would be a mean to defeat pretty much any security measure implemented in the language.
The Rust community caters to people who are a bit obsessive about safety (including myself) and Rust developers tend to consider this a bug in the design of the Go language (there are a few, albeit much harder to achieve, issues that are vaguely comparable in Rust and they are considered bugs in the current design of Rust). The Go community tends to attract people who are more interested in shipping than in guarantees, and Go developers who are aware of this issue tend not care and assume that this is never going to happen in practice (which may or may not be true, I haven't checked).
isn’t that the point of languages that have first class actor models something something?
> is there actually a programming language that makes race conditions impossible
To my knowledge, no.
> if the existence of races makes a language unsafe, then aren't all languages unsafe?
Are we talking about "data races" or "race conditions" One can lead to the other, but race conditions are a much bigger set.
AIUI It's impossible for any language level controls to prevent any and all race conditions, because some are happening outside of the binary/process/computer.
Data races, OTOH are almost trivial to protect against - a contestable thing must have a guard that ensures a writer has exclusive access to that thing for the duration of the write.
Some languages do this with mutually exclusive locks (mutex/semaphore/go channels), some languages/paradigms do this by never having shareable objects (Functional Programming/Pass by Value), and some (Rust) are doing this with the compile time checks and firm rules on a single writer.
By that standard it also incorrectly categorizes rust as memory safe.
> By that standard
What standard?
Or perhaps because you are using an uncommon definition for "memory safety".
> Languages that are not memory safe include C, C++, and assembly.
False.
C and C++ are not memory safe if you use the most common and most performant implementations, sure.
At some point these folks are going to have to accept that caveat
C and C++ as defined by their current standards are memory unsafe. You may argue that some specific implementations manage to stay as memory safe as they can get away with, but even then, features like union prevents a fully memory-safe implementation.
> C and C++ as defined by their current standards are memory unsafe.
I don’t think the spec says one way or another (but please correct me if you find verbiage indicating that the language must be memory unsafe).
It’s possible to make the whole language memory safe, including unions. It’s tricky, but possible.
Someone else mentioned Fil-C but Fil-C builds on a lot of prior art. The fact that C and C++ can be memory safe is no secret to those who understand language implementation.
By definition, C and C++ are memory safe as long as you follow the rules. The problem is that the rules cannot be automatically checked and in practice are the source of unenumerable issues from straight up bugs to subtle standards violations that trigger the optimizer to rewrite your code into what you didn’t intend.
But yes, fil-c is a huge improvement (afaik though it doesn’t solve the UB problem - it just guarantees you can’t have a memory safety issue as a result)
He's talking about Fil-c
Now do type safety.