Live data from Hacker News

Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

verdagon.dev

61–70 of 143 posts

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#61

The way you make garbage collection deterministic is not by doing regions but by making it concurrent. That’s increasingly common, though fully concurrent GCs are not as common as “sorta concurrent” ones because there is a throughput hit to going fully concurrent (albeit probably a smaller one than if you partitioned your heap as the article suggests). Also, no point in calling it “tracing garbage collection”. Its ju…

Using concurrent GC has various advantages but in no way makes it deterministic .

True, not by itself.

But concurrent GC is the basis for making deterministic GC, since it gives you the option of scheduling GC work whenever you like rather than pausing the world.

Some concurrent GCs are also deterministic while others aren’t. I’ve written both kinds.

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#62
After pondering, my single favorite capability of rust is this:

  fn modify(val: &mut u8) {
      // ...
  }
No other language appears to have this seemingly trivial capability; their canonical alternatives are all, IMO, clumsier. In light of the article, is this due to Rust's memory model, or an unrelated language insight?

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#63
post #54
post #41

Earlier quoted context omitted.

The borrow checker is only one component of the means by which Rust statically enforces thread safety. If you design a language that doesn't allow pointers to be shared across threads at all, then you wouldn't need a borrow checker. Likewise if you have an immutable-only language. What's interesting about Rust is that it actually supports this safely, which is still unbelievable sometimes (like being able to send ref…

> If you design a language that doesn't allow pointers to be shared across threads at all, then you wouldn't need a borrow checker. Is that actually true? I'm pretty sure you need the borrow checker even for single threaded Rust to prevent use after frees.

Let me clarify: "wouldn't need a borrow checker for the specific requirement of ensuring thread safety". Clearly the borrow checker is quite useful in single-threaded contexts on its own. :P The point is just that it's perfectly valid to have a language that doesn't have "reference semantics" at all.

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#64

Earlier quoted context omitted.

The first part - that the Rust borrow checker and overall memory model ensures thread/async safety - is true. I cannot speak to the second part - that other systems don't have this assurance.

Just the borrowck isn't enough, you need the Send and Sync marker traits. Marker traits are something lots of languages could do but they'd be useless (or always unsafe) without a lot of other machinery Rust had already.

And Sync might just be there for performance, I think you could get away with only Send if you didn't mind some additional copying?

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#65

Earlier quoted context omitted.

> Also, no point in calling it “tracing garbage collection”. You're against more explicit naming just for the sake of it? In the literature reference counting is also referred to as a type of garbage collection, and doesn't involve tracing. If you talking about a specific context you can probably drop the "tracing", but in a general article like this it would just be very confusing? This way, someone can google "trac…

The literature does not always put the “tracing” in front of the “garbage collection”. For example, nobody says that Objective-C is garbage collected just because it has ARC. Nobody says that C++ is garbage collected even though shared_ptr is widespread. And systems that do tracing GC just call it GC (see for example https://www.oracle.com/webfolder/technetwork/tutorials/obe/j... ) To think clearly about the tradeoff…

> The literature does not always put the “tracing” in front of the “garbage collection”.

Not always, but often enough that an introductory article that presents an overview of different memory managment techniques should maybe use the longer name to avoid confusion.

And I kinda agree with you, using the name "garbage collection" for RC doesn't really make sense, there is no metaphorical garbage truck driving around to collect your unused memory. :)

What's your opinion on the term "RC with cycle detection" that some use for things like Python's GC?

> And it’s possible to change the guts of a GC while preserving compatibility.

Moving to a conservative GC might also introduce memory leaks, if you're unlucky. But yes, "tracing" gc and rc obeviously behave very differently, and have very different performance considerations.

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#66

Earlier quoted context omitted.

The literature does not always put the “tracing” in front of the “garbage collection”. For example, nobody says that Objective-C is garbage collected just because it has ARC. Nobody says that C++ is garbage collected even though shared_ptr is widespread. And systems that do tracing GC just call it GC (see for example https://www.oracle.com/webfolder/technetwork/tutorials/obe/j... ) To think clearly about the tradeoff…

> The literature does not always put the “tracing” in front of the “garbage collection”. Not always, but often enough that an introductory article that presents an overview of different memory managment techniques should maybe use the longer name to avoid confusion. And I kinda agree with you, using the name "garbage collection" for RC doesn't really make sense, there is no metaphorical garbage truck driving around t…

> Not always, but often enough that an introductory article that presents an overview of different memory managment techniques should maybe use the longer name to avoid confusion.

Referring to garbage collection as tracing garbage collection creates more confusion and should be avoided.

It confuses folks into thinking that there is some garbage collection that isn’t tracing. There’s no such thing.

> What's your opinion on the term "RC with cycle detection" that some use for things like Python's GC?

Depends on how you detect cycles. Python uses a garbage collector. Therefore I would say that python has a GC and is a GC’d language.

> Moving to a conservative GC might also introduce memory leaks, if you're unlucky.

Folks who adopt conservatism in production do so only if they have a story for avoiding those leaks. (That’s what we did in JavaScriptCore.)

> But yes, "tracing" gc and rc obeviously behave very differently, and have very different performance considerations.

Just call it “GC” and everyone will know what you mean. No need to be a contrarian and put “tracing” in front.

And it’s not perf considerations if it’s the difference between your program running at all and crashing. Failing to collect all cycles as RC does would cause a program written in a GC’d language to simply crash if it ran for more than just a short while. Failing to invoke destructors the way RC’d programs expect, which would happen if you tried to switch to GC, will cause observably different behavior in addition to possible performance issues.

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#67

The fact that re-using a slot for a different object of the same type is considered a memory safety technique is ridiculous.

“Safety” is a very overloaded English word with strong connotations, and the popularization of it in the context of “memory safety” has been good in some ways, but has really poisoned the discourse in many others.

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#68
I'm kinda torn. It seems there are only three approaches.

1. laissez-faire / manual memory management (c, c++, etc)

In this approach, the programmer decides everything.

2. dictatorship / garbage collection (java, go, etc)

In this approach, the runtime decides everything.

3. deterministic / lifetime memory management (rust, c with arenas, etc)

In this approach, the problem determines everything.

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#69
post #10

Earlier quoted context omitted.

> Memory safety is just one aspect I feel as though not enough attention is given to how std is designed. For example: [u8], str, Path, and OsStr may be confusing at first, but when you understand why they are there any other approach feels icky. std guides you down a path of caring about things that really should matter (at least if you're only unwrapping provably safe values). Have you considered what happens if no…

> Have you considered what happens if not-utf8 data winds up in an environment variable that you are writing to stdout? What if it contains malicious VT commands? Unless you're talking about terminal bugs in parsing invalid UTF-8 - and parsing invalid UTF-8 is easier than rendering valid UTF-8 - VT commands are UTF-8 compatible. You just need to embed an ASCII escape character.

yeah I think this is an area where rust (and python) just get it wrong. files, the Internet and input devices can all give you invalid Unicode. IMO it's better to have a primary string type that includes invalid Unicode since most algorithms will handle it correctly anyway, and the ones that won't can pretty clearly check and throw errors appropriately (especially since very few algorithms work correctly for all of Unicode in the first place)

Re: Borrow Checking, RC, GC, and Eleven Other Memory Safety Approaches

#70
post #51

Earlier quoted context omitted.

You've got this one wrong. Rust is designed for a specific use case. Most projects are not that use case. Therefore the choice to use Rust is wrong. If GC is an option and you want all the nice parts of Rust, use OCaml

> If GC is an option and you want all the nice parts of Rust, use OCaml So are you saying it would be possible to use a hypothetical "non-GC-enabled" OCaml compiler that complains if GC'd code is invoked/generated, and it would be a similar experience as using Rust?

No, simply because GC isn't an optional part of ocaml's design. You can "disable" it only in the sense that you stop any frees from happening.

In order to do away with Garbage collection you'd need to completely change the type system, and while you might get a result which ends up looking a lot like ocaml, it won't be ocaml any more than ocaml is sml.

This is what Rust started out as, by the way. In my opinion, it should have stayed that way. Post-Mozilla Rust has been nothing but a gigantic disappointment.

Post reply on HN