Memory safety for SerenityOS

Yeah Rust definitely trades easier to write for performance… so you can write code in the model that best fits your access patterns at least as long as its “safe”.

I think you’ll end up making the language too application specific if you change that though… and it will end up not working for various use cases optimally, sure it will work but you won’t be able to write optimal code.

If they just wanted safety checks perhaps Nix would have been an option. Jakt seems kind of like they didn’t want Rust or Nix… and didn’t want C++ so they are reinventing a language that suits themselves but that has all the problems of no mindshare. Rust really would be a good option if it could do UIs…

1 Like

My dream language for an r2 api is rust, however a modern C++ is the most compelling option logistically especially for C++ programmers.

1 Like

People should be open to trying new things.

2 Likes

Nix is very much geared for system configuration and orchestration. A lot of people find its terseness off-putting, especially for describing applications like logic and lazy evaluation, while a great feature in system building, holds it back in a lot of other places.

I’d have liked a Lisp more, but its understandably obvious why that didn’t happen.

That’s not really the problem. We have 20 years of codebase and for some of us 20+ years of experience in C++. I’m happy to try some other languages, but certainly not to throw away all of this work to start over for Haiku R2. What would be the point? What would you keep from Haiku? Why not start a new project instead?

For me, if we’re going to use anything else than C++ for Haiku, the first question will be “how do we integrate it with our existing codebase so we don’t have to start over and throw away all our past work?”. Currently Rust doesn’t really allow that.

Serenity was already in a similar situation despite being much newer. That’s why they decided to write their own language that blends with C++, at least at first.

3 Likes

almost all of these new fangled languages, really suck in performance terms. what can you do with these language that you can’t do in c++

I’m not saying to throw away the existing code, nor did I mean to try new things in the existing project. I was thinking about when working on something new. Choose the right tool for the job. My main case in mind was those Javascript developers who managed to get Javascript on the desktop, and now we’ve got bloated & horrendously inefficient applications because those people didn’t want to learn the right tool for the job.

2 Likes

Modern C++ IS a new thing.

3 Likes

100% agree with that !

Python is a similar age to C++ and so hardly counts as “new fangled”. So I suppose this is a critique of Swift? But it’s not a very good critique, Swift isn’t suited to writing something like the Haiku kernel but there’s no reason to think the performance would be a problem for Haiku application software.

Nix is not intended as a general purpose language and obviously Rust has excellent performance because in that respect it’s occupying the same “Zero cost abstraction” niche as C++. Option<NonZeroU32> is literally the same runtime representation as a 32-bit unsigned integer with a zero sentinel value, except it’s type safe at compile time so you won’t keep screwing it up when coding. Rust is full of these places where the machine code output is identical when you get it right, but you get compiler errors when you get it wrong. Same performance, better safety.

Here maybe WUFFS is more instructive. The problem with C++ wasn’t that you can’t write enough programs you do want, but that it’s far too easy to write programs that are nonsense, which you didn’t want. In fact the C++ standards have a turn of phrase they use frequently, “Ill-formed, no diagnostic required”. This means in the case described what you wrote isn’t a C++ program, it has no meaning, it might do anything, and yet the compiler isn’t even expected to warn you about that. It’s much worse than “Undefined behaviour” which they also use everywhere, because “Ill-formed, no diagnostic required” means from the outset the program never meant anything, even the most obvious stanzas have no meaning in this case, too bad, sucks to be you.

WUFFS is far, far less capable than C++, you certainly can’t write most programs in WUFFS. But that’s actually great because you can’t write ANY of the hopelessly wrong programs you didn’t want. In WUFFS your program can be wrong in the sense that e.g. 1 + 1 = 5 is wrong, but not in the way that pouring a basin of water into the main electrical board for your house is wrong. A badly written WUFFS JPEG thumbnailer might make the sky orange instead of blue, but it can’t accidentally open a network socket or delete files. And the result is that WUFFS gets to go real, real fast while being 100% safe.

That’s what your ambitions should look like, C++ isn’t even looking in the correct direction yet.

2 Likes

In performance benchmarks, c++ easily beats python in most computational tasks, so there’s that …

As a newbie, I can actually pick up this new language in under a day, start writing a program and be reasonably certain of not having messed up too badly. Modern C++ is way too complex, has too many footguns and because of the cbinations of these two, either requires signifincat scrutiny during review or external tooling for static analysis and whatnot or compiler flags. Now, the problem isn’t that these are not available, the problem is these are ‘optional’. It is hard to describe to someone immersed in C++ for decade (or more) but from a newbie POV C++ is a scary monster with 5 heads and 15 tentacles. If I take one wrong step, the monster eats me. Compared to that, lot of newer languages with built-in footgun-protections feel like a gentle tour guide.

3 Likes

You talked about “new fangled languages” and your example is actually Python, a language born in the 1980s?

2 Likes

Anything worth doing, is rarely easy.

2 Likes

Absolutely correct. Question is, who gets to do the difficult parts, and how.

If the human is doing the difficult parts like maintaining state and managing low-level memory construct in their head, history shows it is rife for error, and mistakes are caught in runtime.

If the tooling (beyond compiler, eg. testing, static analysis etc.) does it, situation improves. Code becomes easier to reason with because machine doesn’t make mistakes because it was tired that evening. The mistakes are caught before runtime, but it still requires extra infrastructure (CI etc).

If the compiler does it, situation improves dramatically. Now the mistakes are caught at local machine. Latency, and feedback loop reduce. The developer and reviewer can both focus on higher order logic and architecture over memory and state while still getting benefits of low level optimizations.

Again, the reasoning isn’t that everything must be easy. The reasoning is that anything that doesn’t have to be difficult, shouldn’t be.

4 Likes

The problem in C++ is not what you can’t do, it’s what you can do. Indeed it can do everything, including memory leaks, use after free, and a lot of other problems that simply don’t exist in other languages. It also has wrong defaults for many things due to its C legacy.

For example (just a few ones that come to mind:

  • Pass function arguments by copy by default instead of references
  • All classes are copyable by default, the default copy constructor never does what you want
  • The basic pointer type (C style pointer using *) will just crash if you dereference a NULL pointer, doesn’t provide any ownership guarantee/reference counting, etc

So, yes, you can pass by reference. You can disable the copy constructor. You can use smart pointers. But it results in a lot of “boilerplate” code, there are always at least 2 ways to do a thing, and as a result a lot of time is spent debugging things that the compiler or runtime could have detected for you.

And these are all problems that were already solved a good 10 years before C had been invented.

Yes, indeed, but that is not a job for the Haiku project. It’s possible in a younger project like Serenity or in a project that decided to do so from the very start like Redox OS. In our case, we’ll have to remain in C++ for large parts of our codebase at least, for the years to come. It doesn’t matter if we like it or not. People who really don’t like it can go and work on another OS project, maybe take some ideas from Haiku and bring them there.

There’s just a big difference between “what if we started a project now?” and “ok, we have 20 years of past work and millions of lines of code, how do we finish and ship it?”

6 Likes

Safety by compiler design isn’t possible in C++. See Theseus-os for an example of intralingual OS development whose development depends on Rust safety to offload runtime checks to compile time where redundant ones can be reduced out.

Writing an OS where formerly-runtime functions are offloaded to a custom compiler backend and ABI can’t be done when using a hodgepodge of languages. Intralingual means C++ and any other non-safe code language is disallowed (other than WebAssembly bytecode of course) might make the whole ecosystem more secure and performant at the same time.

You can add run time checks to achieve C/C++ memory safety at compile time. Then you can guarantee that the program is either memory safe or crashes. AddressSanitizer and MemorySanitizer get you 90% of the way there. You’d need to add checks for integer (over|under)flow and use after return (e.g. returning a pointer to a stack allocated variable) to get all the way there, I think. But the performance hit is pretty unattractive. There used to be a project with some clever ways of achieving memory safety in C for llvm called SAFECode.

https://clang.llvm.org/docs/AddressSanitizer.html
https://clang.llvm.org/docs/MemorySanitizer.html

Writing an OS in SafeC might be possible the same way that TheseusOS uses a custom Rust compiler (to disallow “unsafe” code in external application code and third-party libraries) but like TheseusOS, the stable ABI would still have to be bytecode so that all of the programs satisfy the safety guarantee.

Is there anyway to reduce that boiler plate with a api extension ?