Live data from Hacker News

Giving C a superpower: custom header file (safe_c.h)

hwisnu.bearblog.dev

201–210 of 277 posts

Re: Giving C a superpower: custom header file (safe_c.h)

#201
post #77

Earlier quoted context omitted.

IDK about Fil-C, but in Java garbage collector actually speeds up memory management compared to C++ if you measure the throughput. The cost of this is increased worst-case latency. A CLI tool (which most POSIX tools are) would pick throughput over latency any time.

> in Java garbage collector actually speeds up memory management compared to C++ if you measure the throughput If I had a dollar for every time somebody repeated this without real-world benchmarks to back it up...

I wish I could upvote this 100 times

Re: Giving C a superpower: custom header file (safe_c.h)

#202
post #193

Does the StringView/Span implementation here seem lacking? If the underlying data goes away, wouldn't the pointer now point to an invalid freed location, because it doesn't track the underlying data in any way?

That's what std::string_view and std::span are, though. They're views / borrows over the underlying data, minus the kind of protections something like Rust has about lifetimes of the underlying data vs the borrow. The benefit of these types is that they're a pair of pointer+size, instead of just a bare pointer without a known size.

True, I guess I was expecting if you were reimplementing these with additional protections, why not add the protection using the custom pointer reimplementations to ensure no use after frees. Seems like a missed opportunity.

Re: Giving C a superpower: custom header file (safe_c.h)

#203

Earlier quoted context omitted.

Outside of hobbyist things, performance-critical code is the only responsible use case for a non-memory safe language like C in 2025, so of course it does. (Even that window is rapidly closing, though; languages like Rust and Swift can be better than C for perf-critical things because of the immutability guarantees.)

> Outside of hobbyist things, performance-critical code is the only responsible use case for a non-memory safe language like C in 2025, so of course it does. Maybe; I sometimes write non-hobbyist non-performance-critical code in C. I'm actually planning a new product for 2026 that might be done in C (the current iteration of that product line is in Go, the previous iteration was in Python). I've few qualms about writ…

> I've few qualms about writing the server in C.

Bad Unicode support. Lack of cross platform system libraries. Needing to deal with CMake / autotools / whatever. Poor error handling. No built in string, list or map types. No generics. Nullability. No sum types. No option, tuples or multi returns. Generally worse IDE support than a lot of languages. No good 3rd party package ecosystem. The modern idiocy of header files. Memory bugs. Debugging memory corruption bugs. …

I mean, yeah other than all those problems, C is a great little language.

Re: Giving C a superpower: custom header file (safe_c.h)

#205

Earlier quoted context omitted.

No, atomics do have a performance penality compared to the equivalent single threaded code due to having to fetch/flush the impacted cache lines in the eventuality that another thread is trying to atomically read/write the same memory location at the same time.

Atomics have almost no impact when reading, which is what would happen in a shared pointer the vast majority of the time.

I think it's pretty rare to do a straight up atomic load of a refcount. (That would be the `use_count` method in C++ or the `strong_count` method in Rust.) More of the time you're doing either a fetch-add to copy the pointer or a fetch-sub to destroy your copy, both of which involve stores. Last I heard the fetch-add can use the "relaxed" atomic ordering, which should make it very cheap, but the fetch-sub needs to use the "release" ordering, which is where the cost comes in.

Re: Giving C a superpower: custom header file (safe_c.h)

#206

Earlier quoted context omitted.

Well, basically, yeah, if your platform lacks support for atomics, or if you'd need some extra functionality around the shared pointer like e.g. logging the shared pointer refcounts while enforcing consistent ordering of logs (which can be useful if you're unfortunate enough to have to debug a race condition where you need to pay attention to refcounts, assuming the extra mutex won't make your heisenbug disappear), o…

Does there exist any platform which has multithreading but not atomics? Such a platform would be quite impractical as you can't really implement locks or any other threading primitive without atomics.

The boring answer is that standard atomics didn't exist until C++11, so any compiler older than that didn't support them. I think most platforms (certainly the popular desktop/server platforms) had ways to accomplish the same thing, but that was up to the vendor, and it might not've been well documented or stable. Infamously, `volatile` used to be (ab)used for this a lot before we had proper standards. (I think it still has some atomic-ish properties in MSVC?)

Re: Giving C a superpower: custom header file (safe_c.h)

#207

Does the StringView/Span implementation here seem lacking? If the underlying data goes away, wouldn't the pointer now point to an invalid freed location, because it doesn't track the underlying data in any way?

I think because it's called `safe_c.h` and is "designed to give C some safety and convenience features from ... Rust", and says "The Memory Management Beast: Slain", you expected to see some level of memory safety, Rust's headline selling point. I did too when I opened the article. But it doesn't at all. Those phrases are all clickbait and slop.

In fact I don't see anything here from Rust that isn't also in C++. They talk about Result and say "Inspired by Rust, Result forces you to handle errors explicitly by returning a type that is either a success value or an error value", but actually, unlike Rust, nothing enforces that you don't just incorrectly use value without checking status first.

It's just some macros the author likes. And strangely presented—why are the LIKELY/UNLIKELY macros thrown in with the CLEANUP one in that first code snippet? That non sequitur is part of what gives me an LLM-written vibe.

Re: Giving C a superpower: custom header file (safe_c.h)

#208
post #193

Earlier quoted context omitted.

That's what std::string_view and std::span are, though. They're views / borrows over the underlying data, minus the kind of protections something like Rust has about lifetimes of the underlying data vs the borrow. The benefit of these types is that they're a pair of pointer+size, instead of just a bare pointer without a known size.

True, I guess I was expecting if you were reimplementing these with additional protections, why not add the protection using the custom pointer reimplementations to ensure no use after frees. Seems like a missed opportunity.

I don’t think there is a way to do this generally without GC, and that leads to significant pitfalls anyway (eg in Java you can accidentally end up holding multi-GB strings in memory because a few references to short substrings exist).

Re: Giving C a superpower: custom header file (safe_c.h)

#209
post #176

Earlier quoted context omitted.

> static char buf[64]; In a function? That makes the function not-threadsafe and the function itself stateful. There are places, where you want this, but I would refrain from doing that in the general case.

Holy moly.. Thread safety.. Good point and Bad point. I myself use threads sparsly, so I dont intermix calls between threads..

It also has different behaviour in a single thread. This can be what you want though, but I would prefer it to pass that context as a parameter instead of having it in a hidden static variable.

Re: Giving C a superpower: custom header file (safe_c.h)

#210
post #148

Earlier quoted context omitted.

I don't really agree, at least if the future looks like Rust. I much prefer C and I think an improved C can be memory safe even without GC.

> I think an improved C can be memory safe even without GC That's a very interesting belief. Do you see a way to achieve temporal memory safety without a GC, and I assume also without lifetimes?

C does have the concept of lifetimes. There is just no syntax to specify it, so it is generally described along all the other semantic details of the API. And no it is not the same as for Rust, which causes clashes with the Rust people.
Post reply on HN