Live data from Hacker News

C Is Best (2025)

sqlite.org

481–490 of 574 posts

Re: C Is Best (2025)

#481
post #476
post #432

Earlier quoted context omitted.

Just because the pyramids exist, it means they were easy to build? OS and browser development are seriously hard and took countless expert man hours.

OS can be actually pretty simple to make. Sometimes it's a part of a CS curriculum to make one. If it were so much easier to do it in other languages (e.g. in Rust), don't you think we would already be using them?

https://github.com/flosse/rust-os-comparison

Writing a toy one? Sure.

Writing a real one? Who's gonna write all the drivers and the myriad other things?

And the claim was not that it's "so much easier", but that it is so much easier to write it in a secure way. Which claim is true. But it's still a complex and hard program.

(And don't even get started on browsers, it's no accident that even Microsoft dropped maintaining their own browser).

Re: C Is Best (2025)

#482
post #451

Earlier quoted context omitted.

None of that matters: what is your application going to do if it tries to allocate 3mb of data from your 2mb allocator? This is the far more meaningful part of the original comment: > and furthermore most code is not in a position to do anything other than crash in an OOM scenario Given that (unlike a language such as Zig) Rust doesn’t use a variety of different allocator types within a given system, choosing to reli…

Since we're talking about SQLite, by far the most memory it allocates is for the page cache. If some allocation fails, the error bubbles up until a safe place, where some pages can be dropped from the cache, and the operation that failed can be tried again. All this requires is that bubbling up this specific error condition doesn't allocate. Which SQLite purportedly tests. I'll note that this is not entirely dissimil…

Sure, and this is completely sensible to do in a library.

But that’s not the point: what can most applications do when SQLite tells them that it encountered a memory error and couldn’t complete the transaction?

Abort and report an error to the user. In a CLI this would be a panic/abort, and in a service that would usually be implemented as a panic handler (which also catches other errors) that attempts to return an error response.

In this context, who cares if it’s an OOM error or another fatal exception? The outcome is the same.

Of course that’s not universal, but it covers 99% of use cases.

Re: C Is Best (2025)

#483

Earlier quoted context omitted.

You don't have to allocate to print to stdout if that's what you're asking.

And then whatever thing that is collecting and forwarding(if applicable) the logs needs to be entirely allocation free?

It just needs to have whatever memory it needs statically allocated.

Re: C Is Best (2025)

#484

Earlier quoted context omitted.

In Zig's case, the entire stdlib never allocates on failure, and most libraries follow the same pattern. The philosophy of Zig is allocation/creation can fail, but freeing/destroying must never fail. It's caused me to be really thoughtful with how I design my data structures, and often made me use better ways of representing metadata.

How do you log or tell the world about the state of the program without allocating?

Good grief all kinds of ways. Practically all the same countless possible paths as those that require allocating.

Re: C Is Best (2025)

#485

Earlier quoted context omitted.

If you allocate a relatively big chunk of memory for each unit of work, and at some point your allocation fails, you can just drop that unit of work. What is not practical?

I think in that case overcommit will happily say the allocation worked. Unless you also zero the entire chunk of memory and then get OOM killed on the write. I suppose you can try to reliable target "seriously wild allocation fails" without leaving too much memory on the table. 0: Heuristic overcommit handling. Obvious overcommits of address space are refused. Used for a typical system. It ensures a seriously wild al…

> See this recent discussion on what can happen when turning off overcommit:

What are you referring to specifically? Overcommit is only (presumably) useful if you are using Linux as a desktop OS.

Re: C Is Best (2025)

#486

Earlier quoted context omitted.

They talk about this here: https://sqlite.org/testing.html#statement_versus_branch_cove... ...saying that for a statement `if( a>b && c!=25 ){ d++; }`, they use 100% machine-code branch coverage as a way of determining that they've evaluated this in `a b && c==25`, and `a>b && c!=25`. (C/C++) branch coverage tools I've used are less strict, only requiring that takes both if and else paths. One could imagine a better…

Hmm, so in a language that does automatic bounds checking, the compiler might translate a line of source code like: let val = arr[i] to assembly code like: cmp rdx, rsi ; Compare i (rdx) with length (rsi) jae .Lpanic_label ; Jump if i >= length ; later... .Lpanic_label: call core::panicking::panic_bounds_check Are they saying with "correct code" the line of source code won't be covered? Because the assembly instructi…

I think they're saying it's not covered: not only because `call` isn't ever reached but also because they identify `jae` as a branch and see it's always not taken. (If there were no lines in your `; later...` section and the branch were always taken, they'd still identify the `jae` as not covered.)

It might be reasonable to redefine their metric as "100% branch coverage except for panics"...if you can reliably determine that `jae .Lpanic_label` is a panic jump. It's obvious to us reading your example of course but I don't know that the compiler guarantees panics always "look like that", and only panics look like that.

Re: C Is Best (2025)

#487
post #482

Earlier quoted context omitted.

Since we're talking about SQLite, by far the most memory it allocates is for the page cache. If some allocation fails, the error bubbles up until a safe place, where some pages can be dropped from the cache, and the operation that failed can be tried again. All this requires is that bubbling up this specific error condition doesn't allocate. Which SQLite purportedly tests. I'll note that this is not entirely dissimil…

Sure, and this is completely sensible to do in a library. But that’s not the point: what can most applications do when SQLite tells them that it encountered a memory error and couldn’t complete the transaction? Abort and report an error to the user. In a CLI this would be a panic/abort, and in a service that would usually be implemented as a panic handler (which also catches other errors) that attempts to return an e…

The topic is whether Rust should be used to re-implement SQLite.

If SQLite fails to allocate memory for a string or blob, it bubbles up the error, frees some data, and maybe tries again.

Your app may be "hopeless" if the error bubbles up all the way to it, that's your choice, but SQLite may have already handled the error internally, retried, and given your answer without you noticing.

Or it may at least have rolled back your transaction cleanly, instead of immediately crashing at the point of the failed allocation. And although crashing should not corrupt your database, a clean rollback is much faster to recover from, even if your app then decides to crash.

Your app, e.g. an HTTP server, might decide to drop the request, maybe close that SQLite connection, and stay alive to handle other ongoing and new requests.

SQLite wants to be programmed in a language were a failed allocation doesn't crash, and unlike most other code, SQLite is actually tested for how it behaves when malloc fails.

Re: C Is Best (2025)

#488
post #384

Earlier quoted context omitted.

Less glue and avoidance of nails and screws doesn't make it sturdier. Fastening things strongly makes your furniture sturdier than not doing so. Antiques suck as often as they don't, and moreover you are only seeing the ones that survived without a base rate to compare it to; they succeeded in spite of power tools, but power tools would have made the same object better. Comparing it to AI makes no sense. Invoking it…

There was an interesting video on YT where an engineer from a fastener company joined a carpenter to compare their products with traditional joints. The traditional joints held up very well and even beat the engineered connectors in some cases. Additionally one must be careful with screws and fasteners: if they’re not used according to spec, they may be significantly weaker than expected. The presented screws had to…

> Glue is typically used in traditional joinery, so less glue would actually have a negative effect.

And a lot of traditional joinery is about keeping the carcase sufficiently together even after the hide glue completely breaks down so that it can be repaired.

Modern glues allow you to use a lot less complicated joinery.

Re: C Is Best (2025)

#489
post #353

Earlier quoted context omitted.

> Surely that gap has been filled for at least a decade, even if only by Rust itself? I think this is the argument made by the "Rust Evangelism Task Force" -- that Rust provides the features that C and C++ are missing. What i meant by "gap" is "the distance between C or C++ and Rust is greater then the distance between C++ and Go (in Go's target use case) or between Java and Kotlin". For the record, I do think all of…

> the distance between C or C++ and Rust is greater then the distance between C++ and Go (in Go's target use case) or between Java and Kotlin What, exactly, does distance mean here? The other explicitly told design consideration for Go was for it to "feel like a dynamically-typed language with statically-typed performance". In other words, the assumption was that Googlers were using C++ for network servers not becaus…

> Keep in mind that Go was created before we knew how to make actually dynamically-typed languages fast.

Would you mind elaborating on this? The strongtalk heritage of VMs has been around for a while now, and certainly before go was started.

Re: C Is Best (2025)

#490
post #481
post #476

Earlier quoted context omitted.

OS can be actually pretty simple to make. Sometimes it's a part of a CS curriculum to make one. If it were so much easier to do it in other languages (e.g. in Rust), don't you think we would already be using them?

https://github.com/flosse/rust-os-comparison Writing a toy one? Sure. Writing a real one? Who's gonna write all the drivers and the myriad other things? And the claim was not that it's "so much easier", but that it is so much easier to write it in a secure way. Which claim is true. But it's still a complex and hard program. (And don't even get started on browsers, it's no accident that even Microsoft dropped maintain…

The toy one can still be as highly concurrent as the the real one. The amount of drivers written for it doesn't matter.

The point is if it were much easier, then they would overtake existing ones easily, just by adding features and iterating so much faster and that is clearly not the case.

>>difficulty of building safe, fast and highly-concurrent C

This was the original claim. The answer is, there is a tonne of C code out there that is safe, fast and concurrent. Isn't it logical? We have been using C for the last 50 years to build stuff with it and there is a lot of it. There doesn't seem to be a big jump in productivity with the newer generation of low level languages, even though they have many improvements over C.

This is anecdotal, I used to do a lot of low level C and C++ development. And C++ is a much bigger language then C. And honestly I don't think I was ever more productive with it. Maybe the code looked more organized and extendable, but it took the same or larger amount of time to write it. On the other hand when I develop with Javascript or C#, I'm easily 10 times more productive then I would be with either C or C++. This is a bit of apples and oranges comparison, but what I'm trying to say is that new low level languages don't bring huge gains in productivity.

Post reply on HN