Live data from Hacker News

Making C++ safe without borrow checking, reference counting, or tracing GC

verdagon.dev

11–20 of 226 posts

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#11
post #6
post #2

See also: Thomas Neumann's current proposal for memory safe C++ using dependency tracking: - https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p27... Google's proposal for memory safety using Rust-like lifetime analysis: - https://discourse.llvm.org/t/rfc-lifetime-annotations-for-c/... - https://github.com/google/crubit/tree/main/lifetime_analysis

And Microsoft' work on Visual C++ lifetime checker and SAL, as well. It will never be perfect, but every little improvement helps.

> It will never be perfect, but every little improvement helps.

Or it might convince people to stay longer on a plane with a provably [0] terrible safety record.

[0] https://alexgaynor.net/2020/may/27/science-on-memory-unsafet...

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#12
The reason why safety in C++ is difficult to achieve is due to the memory model used by C and C++. The memory model is a flat space provided by the OS that can be addressed by pointers. In this sense, C++ is similar to assembly code. A language like Java, on the other hand, assumes a different model where you can only access objects with well defined behavior. To change this, one needs to disallow the use of native pointers in C++ or make them less powerful, like Java did.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#13
post #6

Earlier quoted context omitted.

And Microsoft' work on Visual C++ lifetime checker and SAL, as well. It will never be perfect, but every little improvement helps.

> It will never be perfect, but every little improvement helps. Or it might convince people to stay longer on a plane with a provably [0] terrible safety record. [0] https://alexgaynor.net/2020/may/27/science-on-memory-unsafet...

To put matters into perspective, Rust reference implementations depend on C++ toolchains.

Same applies to all major Ada, Java, .NET, Swift, Ocaml and Haskell implementations. And any GPGPU toolchain.

Which kind of shows it isn't going anywhere and those planes have to be improved no matter what.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#14

> Tracing GC is the simplest model for the user, and helps with time management and development velocity, two very important aspects of software engineering. > Borrow checking is very fast, and helps avoid data races. One thing many people seem to assume is that not having to care about memory means you can program faster and get to your goal faster. As the author here seems to do. However as it turns out, if your pr…

I don't write Rust.

But here is what you said and what the author said don't conflict with each other, and it has been on my mind for a while.

People who write similar code, or work on things for decades usually don't really think through what "sketch out some code" looks like. They spend most of their time on refactoring things that has clear use-cases, but not well-defined API boundaries within the component, or between components. So ownerships, nullability checks, data race checks are all comes very naturally as a starter.

But there are other side of the world, where people constantly sketching out something, for things like creative arts, high-level game logic, data analysis, machine learning etc. Now putting yourself in that position, the syntax noises are actively in the way of this type of programming. Ownerships, even nullability checks are not helpful if you just want to have partial code running and checking if it draws part of the graph. This is a world Python excels, and people constantly complaining about why this piece of Python code doesn't have type-annotation.

We may never be at peace between these two worlds, and this manifest itself somewhat into the "two-language problem". But that to me, is when someone mean "development velocity is faster".

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#15
post #8
post #7

Earlier quoted context omitted.

Ideally we would have -fsafe and [[unsafe]], but it will take years for something like that.

Presuming syntax for “unsafe” that gracefully degrades in non-aware compilers, why couldn’t a particular compiler start doing it right now, starting with a very trivial safety checker than can be iteratively improved upon once the framework is in place?

You can have it today on Circle, but its relationship with some C++ folks is complicated.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#16

The reason why safety in C++ is difficult to achieve is due to the memory model used by C and C++. The memory model is a flat space provided by the OS that can be addressed by pointers. In this sense, C++ is similar to assembly code. A language like Java, on the other hand, assumes a different model where you can only access objects with well defined behavior. To change this, one needs to disallow the use of native p…

You just need an unsafe keyword.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#18

> Tracing GC is the simplest model for the user, and helps with time management and development velocity, two very important aspects of software engineering. > Borrow checking is very fast, and helps avoid data races. One thing many people seem to assume is that not having to care about memory means you can program faster and get to your goal faster. As the author here seems to do. However as it turns out, if your pr…

I would love a language (or C++ subset!) where we could get the benefits of that secret sauce, while mitigating or avoiding some of its downsides.

Like Boats said, the borrow checker works really well with data, but not so well with resources. I'd also opine that it works well with data transformation but struggles with abstraction (both the good and bad kinds), works well with tree-shaped data but struggles with programs where the data has more intra-relationships (like GUIs and more complex games), and works well for imposing/upholding constraints but can struggle with prototyping and iterating.

These are a nice tradeoff already, but if we can design some paradigms that can harness the benefits without its particular struggles, that would be pretty stellar.

One promising meta-direction is to find ways to compose borrowing with mutable aliasing. Some promising approaches off the top of my head:

* Vale-style "region borrowing" [0] layered on top of a more flexible mutably-aliasing model, either involving single-threaded RC (like in Nim) or generational references (like in Vale).

* Forty2 [1] or Verona [2] isolation, which let us choose between arenas and GC for isolated subgraphs. Combining that with some annotations could be a real home run. I think Cone [3] was going in this direction for a while.

* Val's simplified borrowing (mutable value semantics [4]) combined with some form of mutable aliasing (like in the article!).

* Rust does this with its Rc/RefCell, though it doesn't compose with the borrow checker and RAII as well as it could, IMO.

[0] https://verdagon.dev/blog/zero-cost-borrowing-regions-part-1... (am author)

[1] http://forty2.is/

[2] https://github.com/microsoft/verona

[3] https://cone.jondgoodwin.com/

[4] https://www.jot.fm/issues/issue_2022_02/article2.pdf

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#19

The reason why safety in C++ is difficult to achieve is due to the memory model used by C and C++. The memory model is a flat space provided by the OS that can be addressed by pointers. In this sense, C++ is similar to assembly code. A language like Java, on the other hand, assumes a different model where you can only access objects with well defined behavior. To change this, one needs to disallow the use of native p…

That's pretty much what the article says though. "Don't use traditional pointers" is a fairly trivial rule to enforce via static analysis, and constructs like unique_ptr are syntactically identical anyway.

The bit that has me confused is that it's inventing a new term, "borrowing affine style", to describe a longstanding paradigm that has traditionally been called "RAII". Now, neither term is very clear, but surely it's better to use the existing confusing jargon instead of inventing new terms.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#20
post #13

Earlier quoted context omitted.

> It will never be perfect, but every little improvement helps. Or it might convince people to stay longer on a plane with a provably [0] terrible safety record. [0] https://alexgaynor.net/2020/may/27/science-on-memory-unsafet...

To put matters into perspective, Rust reference implementations depend on C++ toolchains. Same applies to all major Ada, Java, .NET, Swift, Ocaml and Haskell implementations. And any GPGPU toolchain. Which kind of shows it isn't going anywhere and those planes have to be improved no matter what.

Rust has been bootstrapped for nearly a decade. The rust reference toolchain is built in rust.
Post reply on HN