[TUHS] Hypothetical: Could MULTICS have been written in C, if available?

Dan Cross via TUHS tuhs at tuhs.org
Thu May 28 01:50:34 AEST 2026


On Tue, May 26, 2026 at 10:02 AM Larry McVoy via TUHS <tuhs at tuhs.org> wrote:
> [snip BLS's comments about cars, instruments, and programs]
> Amen to all of this.  And I think I've posted this but it is worth a repeat
> since you mentioned sports cars.
>
> When Travis was looking at C, I told him that C is like driving a sports
> car on a narrow, twisty road with no guard rails and a there is a cliff
> on one side of the road.  So it is not for people who want to look at their
> phone while driving, that's how you die.  On the other hand, if you are a
> good driver, that narrow, twisty road and that car are glorious.

But you have also said that if you take someone out on your boat, and
they won't wear a flotation device, that's the last time they're going
out on your boat.

Sports cars can be fun!  So can motorcycles.  I once raced another
jarhead to the main gate at 29 Palms; he was in a Ford Cobra and I was
on a Triumph; British engineering on a lean bike versus a V8 in a
sleek form factor: who would win?! I let off the throttle when I hit
110 MPH and it was clear that I had.

In retrospect, however, that was not a good idea. My Harley can hit
that without breaking a sweat, but going that fast simply isn't smart:
if I'd hit a pothole wrong? It could have been a bad day; I probably
wouldn't have cared since I'd be dead, though.

> Languages like Rust are all the rage, but they take away a lot of the joy
> of making stuff work well in C.  I get it, there are far more programmers
> that want to look at their phone than there are programmers who are good
> enough to program in C.

The framing of "good enough to program in C" is the wrong way to look at it.

If the sports car goes off the side of the mountain, 99 times out of
100 the only one who ends up in the morgue is the driver: tragic,
perhaps, but one's own damn fault. On the other hand, if the school
bus goes off the road, the consequences are far worse. Most of the
time software is Not a sports car; it's more like a school bus loaded
with kids.

Side note: when I was stationed in Twentynine Palms, I'd ride over to
LA on the weekends occasionally to see friends. Coming down out of the
high desert heading towards Palm Springs, you went through a series of
very twisty roads; lots of tire marks along the highway where people
drove fast for "fun", drifted around curves; that kind of thing. And
one set I always remember that went OFF the road, and disappeared over
the edge of a cliff; a 30 foot drop on the other side: I'm pretty sure
no one survived that. You sure you want to take that risk?

Rust isn't for people who want to look at their phones; it's for
people who value life jackets and seatbelts and think that school
buses should be as safe as we can make them. I would argue that it
demands _more_ of the programmer to write correct Rust than it does to
write correct C, particularly if any amount of `unsafe` is involved;
but if you do, the guarantees that the language gives you are much
stronger. Safe Rust code cannot segfault or have data races; period.

On the other hand, it's super easy to inadvertently stumble into
undefined behavior and segfaults, even in extremely well-written C.
Here's an example from the bitkeeper source. I randomly looked at
https://github.com/bitkeeper-scm/bitkeeper/blob/master/src/port/bkd_server.c,
and notice the following on lines 58 and 59:

```
|        while (nav[i++] = av[j++]);
|        assert(i < 100);
```

Here, the contents of the string array `av` are copied into `nav`,
which is defined as, `char *nav[100];`. Near as I can tell, this is
called directly with an only slightly-modified version of the
arguments to `main`, but nothing checks that the input argument vector
will not overflow `nav` before the loop.  The `assert` is obviously
meant to catch this, but since it happens _after_ the loop, by the
time you run into it, you've probably already clobbered what was
around `nav` on the stack; indeed, I can trigger this on a local
build, and the resulting stack frame is junk.  Moreover, the code as
written is wrong: the array has space for 100 elements, thus indices
0..99 are valid. Suppose that i==99'th element is the terminating nil
pointer, then the `i++` index expression would set nav[99] and then
set i to 100; that's perfectly valid, but in that case, the `assert`
will still fire: that is, the last element in `nav` is inaccessible as
written.

By contrast, in Rust, if one were copying into `nav: [*mut
std::ffi::c_char; 100]`, then in a build with array bounds checking
turned on (the default), this would trap on an attempt to access an
element beyond the end of the array. More idiomatically, however, one
would probably use a `Vec<*mut std::ffi::c_char>` and copy into it,
letting it handle the details of dynamically sizing the underlying
vector.

Of course, this is kind of a silly example: only a jerk is going to
give more than 100 arguments to `bk` in order to trigger this bug, but
the point is, you're going to invariably find this kind of thing in
_any_ large C code base, even ones written by legitimate experts
extremely familiar with the language.

        - Dan C.


More information about the TUHS mailing list