Live data from Hacker News

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

hwisnu.bearblog.dev

131–140 of 277 posts

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

#132

Earlier quoted context omitted.

Which platforms might that be? Even MIPS has atomics (at least pointer sized last i checked).

AFIAK, and I'm not MIPS expert, but I believe it doesn't have the ability to add a value directly to a memory address. You have to do something like // Not real MIPS, just what I've gleaned from a brief look at some docs LOAD addr, register ADD 1, register STORE register, addr The LOAD and STORE are atomic, but the `ADD` happens out of band. That's a problem if any sort of interrupt happens (if you are multi-threadin…

On MIPS you can simulate atomics with a load-linked/store-conditional (LL/SC) loop. If another processor has changed the same address between the LL and SC instructions, the SC fails to store the result and you have to retry. The underlying idea is that the processors would have to communicate memory accesses to each other via the cache coherence protocol anyway, so they can easily detect conflicting writes between the LL and SC instructions. It gets more complicated with out-of-order execution...

    loop: LL r2, (r1)
          ADD r3, r2, 1
          SC r3, (r1)
          BEQ r3, 0, loop
          NOP

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

#133

Earlier quoted context omitted.

The popular C compilers include a static analyzer and a runtime sanitizer. What features do you consider proper C? The C standard has always been about standardization of existing compilers, not about prescribing features.

By "static analysis" you mean unsound, best-effort analyzers which try to study code as-is, rarely allow extra annotations, and tolerate false negatives and even positives by design. While these are a huge improvement over no extra tooling, they don't compare to analyzers like Frama-C plugins, which demand further annotations/proofs if necessary to show code is free of UB, and you can provide further to show your cod…

Yes, I do. I know they are very different from real correctness verifiers, but it's not like the people only using the compiler has no way of preventing trivial UB bugs. UB also is really only a language concept and nobody is writing code for the abstract C machine.

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

#134

Intentionally or not, this post demonstrates one of the things that makes safer abstractions in C less desirable: the shared pointer implementation uses a POSIX mutex, which means it’s (1) not cross platform, and (2) pays the mutex overhead even in provably single-threaded contexts. In other words, it’s not a zero-cost abstraction. C++’s shared pointer has the same problem; Rust avoids it by having two types (Rc and…

Unfortunately, for C++, thats not true. At least with glibc and libstdc++, if you do not link with pthreads, then shared pointers are not thread-safe. At runtime it will do a symbol lookup for a pthreads symbol, and based off the result, the shared pointer code will either take the atomic or non-atomic path. I'd much rather it didnt try to be zero-cost and it always used atomics...

This is, impressively, significantly worse than I realized!

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

#135

Earlier quoted context omitted.

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.

Certainly such systems can pretty readily exist. You merely need atomic reads/writes in order to implement locks. You can't create userspace locks which is a bummer, but the OS has the capability of enforcing locks. That's basically how early locking worked. The main thing needed to make a correct lock is interrupt protection. Something every OS has. To go fast, you need atomic operations. It especially becomes impor…

I wrote "multithreaded" but I really meant "multicore". If two cores are contending for a lock I don't see how irq protection help. As long as there is only one core, I agree.

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

#136

Intentionally or not, this post demonstrates one of the things that makes safer abstractions in C less desirable: the shared pointer implementation uses a POSIX mutex, which means it’s (1) not cross platform, and (2) pays the mutex overhead even in provably single-threaded contexts. In other words, it’s not a zero-cost abstraction. C++’s shared pointer has the same problem; Rust avoids it by having two types (Rc and…

C11 has a mutex API (threads.h), so why would it rely on POSIX? Are you sure it's not an runtime detail on one platform? https://devblogs.microsoft.com/cppblog/c11-threads-in-visual...

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

#137
post #60

Earlier quoted context omitted.

For new projects, I just use Rust: there is zero reason to deal with a garbage collector today. If I'm in C, it's because I care about predictable performance, and why I'm not using Java for that particular project.

https://docs.rs/gc/latest/gc/

Not really sure what relevance a third party library has when discussing the language characteristics.

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

#138
post #114

Any hopes that MSVC will add C23 support before 2040?

If you interpret 23 as hex, that's only five years after the year, which isn't too bad!

I suppose it makes sense that every version that came after "c++0x" should be interpreted in hex.

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

#139

I feel like there might be some value in this header file for some projects, but this is exactly the wrong use case. > In cgrep, parsing command-line options the old way is a breeding ground for CVEs and its bestiary. You have to remember to free the memory on every single exit path, difficult for the undisciplined. No, no, no. Command line options that will exist the entire lifetime of the program are the quintessen…

shouldn't be individually allocated either, arenas for the win

I think that a blanket should/shouldn't recommendation for arenas isn't right. Arenas are a tradeoff:

Pros: preallocating one arena is likely faster than many smaller allocations.

Cons: preallocation is most effective if you can accurately predict usage for the arena; if you can't, then you either overshoot and allocate more memory than you need, or undershoot and have to reallocate which might be less performant than just allocating as-needed.

In short, if you're preallocating, I think decisions need to be made based on performance testing and the requirements of your program (is memory usage more important than speed?). If you aren't preallocating and just using arenas for to free in a group, then I'm going to say using an arena for stuff that is going to be freed by the OS at program exit is adding complexity for no benefit--it depends on your arena implementation (arenas aren't in the C standard to my knowledge).

In general, I'd be erring on the side of simplicity here and not using arenas for this by default--I'd only consider adding arenas if performance testing shows the program spending a lot of time in individual allocations. So I don't think a blanket recommendation for arenas is a good idea here.

EDIT: In case it's not obvious: note that I'm assuming that the reason you want to use an arena is to preallocate. If you're thinking that you're going to call free on the arena on program exit, that's just as pointless as calling free on a bunch of individual allocations on program exit. It MIGHT be faster, but doing pointless things faster is still not as good as not doing pointless things.

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

#140

Intentionally or not, this post demonstrates one of the things that makes safer abstractions in C less desirable: the shared pointer implementation uses a POSIX mutex, which means it’s (1) not cross platform, and (2) pays the mutex overhead even in provably single-threaded contexts. In other words, it’s not a zero-cost abstraction. C++’s shared pointer has the same problem; Rust avoids it by having two types (Rc and…

The shared-pointer implementation isn’t actually shown (i.e. shared_ptr_copy), and the SharedPtr type doesn’t use a pthread_mutex_t.
Post reply on HN