Live data from Hacker News

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

verdagon.dev

41–50 of 226 posts

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

#41
RIP all the modern languages that haven't made any improvements in memory management at all.

There is so much low hanging fruit in programming language design and nobody is picking it up and instead everyone produces marginal improvements over existing languages.

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

#43
post #40

> "We'll instead take and return the vector directly" Won't this clone it?

Not necessarily, although it's a bit complicated to understand in C++.

Starting with C++17, there is a feature called guaranteed copy elision that works for many/most scenarios that you would want. You need to read through the following resources to understand it fully:

https://en.cppreference.com/w/cpp/language/copy_elision https://en.cppreference.com/w/cpp/language/value_category

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

#44
post #27

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…

> The memory model is a flat space provided by the OS that can be addressed by pointers From what I understand this is not true. Pointers cease to be valid the moment you try to leave a single allocation. You get to play around within a single continuous allocation and one past the end, everything further out is playing with fire. Even comparing the "addresses" of two separate allocations is undefined if done with "…

> Pointers cease to be valid the moment you try to leave a single allocation.

For the other readers who might not know what this is referring to, it's pointer provenance. For an introduction to the topic, I always recommend Ralf Jung's blog series, "Pointers Are Complicated":

https://www.ralfj.de/blog/2018/07/24/pointers-and-bytes.html

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

#45
post #17

Use memory arenas and never think about any of this again.

Sadly, untrue. Source: I use memory arenas, and it's still pretty trivial to copy (instead of reference) an object onto a stack and then try to save a pointer to that object. All you need is to leave out one `&` and the compiler won't tell you anything went wrong: it'll cheerfully let you retain a pointer to a stack-based object that is going to die because explicit lifetime analysis isn't a part of the language spec.

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

#46
post #14

Earlier quoted context omitted.

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 be…

I really love parts of rust and kinda hate other parts. but this is what really ruins it for me. I want to play. I want to knock something together and work with it and see what kind of shape it is. rust demands that I cross every last t before I can run it at all. which is great if you already have a crystal notion of what you are building

Yea, different languages for different purposes. Rust is for finished products, not so much for experimentation. When you want to play or experiment you should use Lisp.

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

#47
post #13

Earlier quoted context omitted.

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.

I agree these planes are important and deserve care. At the same time pretty much all suggestions on how to meaningfully improve the safety of those planes boil down to successor languages Cpp2, Carbon etc. or require some other complex manual rewrite of components of said plane. There is an argument to be made for having good out-of-the-box interoperability, however even in some of the most complex and important cod…

The second someone makes a successor language that seamlessly/directly interops with C++ _AND_ has the level of build/IDE tooling that C++/Rust have, I'm on board.

The closest thing right now is Sean Baxter's "Circle" compiler in "Carbon" mode IMO:

https://github.com/seanbaxter/circle/blob/master/new-circle/...

Unfortunately, Circle is closed-source and there's no LSP or other tooling to make the authoring experience nice.

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

#48
post #27

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…

> The memory model is a flat space provided by the OS that can be addressed by pointers From what I understand this is not true. Pointers cease to be valid the moment you try to leave a single allocation. You get to play around within a single continuous allocation and one past the end, everything further out is playing with fire. Even comparing the "addresses" of two separate allocations is undefined if done with "…

It is, for all practical purposes, a flat space in the sense that for bare pointers, operator++ is defined (increments to the next whatever, defined based on type of pointer).

There is no operator++ equivalent in Java to apply to object references (unless you go unsafe); you can't immediately shoot yourself in the foot without the compiler noticing by asking for "the next object after this one" when no such thing exists.

(handwave a bit: of course, you can ask for an object past the last object in any container. That's (a) not the same thing and (b) results in an immediate runtime error in Java, instead of undefined behavior)

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

#49

RIP all the modern languages that haven't made any improvements in memory management at all. There is so much low hanging fruit in programming language design and nobody is picking it up and instead everyone produces marginal improvements over existing languages.

Because implementing a new language and getting it to wide adoption is an enormously challenging task, with a much lower success rate than e.g. SV startups.

Languages that try to implement one new bright idea don't go anywhere, because that's not enough to cause people to switch. At best they serve as examples for feature adoption in other languages.

Look at Rust for example: it seems to be succeeding and gaining adoption, but right now it's still relatively niche (check the number of Rust job postings), and it's taken 17 years to get to this point, with sponsorship from major organizations like Mozilla.

Given this, the idea that there's much low-hanging fruit that's being ignored, that could easily be exploited, seems dubious. What's an example of what you have in mind?

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

#50
post #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 i…

borrowing affine style is more than RAII. borrowing affine style means that there are no pointers, and always one owner. in borrowing affine style your functions take a unique_ptr for everything, if the lifetime of the data needs to live beyond the function, then the function returns a unique_ptr of that data back.

    std::unique_ptr var;
    // init and use var
    var = SomeFunction(std::move(var));
    // use var again.
Note that while in SomeFunction you lose access to var, but since SomeFunction returns it again you don't really lose anything. Of course Somefunction can also return some other unique_ptr that isn't var and you can't control that.

It is an interesting idea, though I'm not sure if I like it for real world code or not.

Post reply on HN