Live data from Hacker News

C23 Implications for C Libraries

htmlpreview.github.io

121–130 of 135 posts

Re: C23 Implications for C Libraries

#121
post #91

Earlier quoted context omitted.

If you do "for (int i = 0; i While two's complement signed rollover can be pretty useful, in 99% of cases you don't need it, and casting to unsigned for the 1% is a worthwhile sacrifice for the better optimizations for the common case, and it'll be pretty clear when you want wrapping or not (and sanitizers will be able to keep reporting signed overflow as errors without false positives).

No, my 'intent' is to get: error: signed integer variable used as array index (-Wsigned-index) `int i`: should be `size_t i` error: comparison of signed to unsigned integer (-Wsigned-comparison) `i Scare quotes on "intent", because I don't write (that particular kind of) obviously broken code in the first place, but the upshot is that i and len both need to be size_t, and anything that lets the compiler obscure that…

The compiler could do those things too (-Wsign-compare is a thing; nothing for signed index though), but that won't change the existing code that uses "for (int ..." (incl. 637K C source files on github), and those warnings could be false positives too (e.g. signed indexes into lookup tables, or keeping using an int32_t after having asserted somewhere before (possibly out of the compiler's vision) that it's non-negative).

Re: C23 Implications for C Libraries

#122
post #48

Earlier quoted context omitted.

If you mean MVSC, it never will, because it now supports C11 and C17, minus the optional annexes from C99 that were dropped in C11, and atomics aren't fully supported as well.

I've heard that they are working on C11 atomics, now that the C++ standard includes for compatibility with C.

Might be, that was the main goal when they gave up on C, just to improve C compatibility to the extent of ISO C++ requirements.

It was the whole change of management that somehow made them backtrack on that decision.

Re: C23 Implications for C Libraries

#123

Earlier quoted context omitted.

Neither. The code wasn't standard C, and it didn't just "happen" to work, either. You probably wouldn't want to build an atomic compare-exchange in standard C, even if it were possible; you find out what the hardware provides and work with that.

> The code wasn't standard C, and it didn't just "happen" to work Thanks, that makes sense. At the risk of sounding pedantic, you did say using nothing but C99 or C90 , implying use of standard features only. > You probably wouldn't want to build an atomic compare-exchange in > standard C, even if it were possible; you find out what the > hardware provides and work with that. Agreed.

Right; I could do it using nothing but standard C features in C source files, by defining some C compatible assembly language routines. The compare_swap primitive can be an external function, e.g.:

  bool cmpswap64(uint64_t *location, uint64_t if_old, uint64_t then_new);
Code that relies on the header doesn't have to process anything compiler-specific. FFI could be used to bind to that function from non-C languages.

Re: C23 Implications for C Libraries

#124

>> One major change in the language is that two’s complement is now mandatory as a representation for signed types. This pleases me greatly. Two's complement won decades ago. This also means they could define integer overflow as 2's complement rollover, which is almost universal but is still considered undefined behavior.

> This also means they could define integer overflow as 2's complement rollover, which is almost universal but is still considered undefined behavior. No, they should not. Integer overflow is in most cases logic error, like division by zero or NULL pointer dereference, so it should stay undefined.

That's only true for the relatively recent and generally unhelpful "nasal demons" interpretation of undefined behavior; under the older concept, which is more like "do whatever the sensible thing would be on the target platform", rollover is probably just what you want.

Re: C23 Implications for C Libraries

#125
post #45

Earlier quoted context omitted.

They could introduce a similar type that is prohibited (checked by the compiler) from occurring in declarations with external linkage (plus some wording regarding casting of data across translation units being undefined behavior for that type). Effectively prohibit it from being used in ABIs. It would then still be useful for intermediate calculations and in macros.

That doesn't work because possibly[2] the most important single use of uintmax_t is the printf specifier "%ju", ie a ABI boundary. Ironically, this is actually one of the only[0] legitimate uses for standard[1] PRI* macros, since that could expand to whichever of "%llu", "%w128u", etc, was appropriate to the caller. 0: And I'm not sure "one of" is actually needed. 1: as opposed to nonstandard ones like PRIu_xlib_atom…

I meant a new, separate type, in addition to the defunct existing (u)intmax_t. For that new type, %j(u) wouldn't apply, but of course a PRI* macro could be added for it as you suggest.

Re: C23 Implications for C Libraries

#126
post #75

Earlier quoted context omitted.

I don't fully understand the need or benefit of having free_sized() available tbh. Spec says it's functionally equivalent to free(ptr) or undefined: If ptr is a null pointer or the result obtained from a call to malloc, realloc, or calloc, where size size is equal to the requested allocation size, this function is equivalent to free(ptr). Otherwise, the behavior is undefined Even the recommended practice does not rea…

> I don't fully understand the need or benefit of having free_sized() available tbh. It's a performance optimization. Allocator implementations spend quite a lot of time in free() matching the provided pointer to the correct size bucket (as to why they don't have something like a ptr->bucket hash table, IDK, maybe it would consume too much memory overhead particularly for small allocations?). With free_sized() this s…

Thanks for your insights, which prompted to actually jump into the malloc.c implementation.

Re: C23 Implications for C Libraries

#127

Earlier quoted context omitted.

> This also means they could define integer overflow as 2's complement rollover, which is almost universal but is still considered undefined behavior. No, they should not. Integer overflow is in most cases logic error, like division by zero or NULL pointer dereference, so it should stay undefined.

That's only true for the relatively recent and generally unhelpful "nasal demons" interpretation of undefined behavior; under the older concept, which is more like "do whatever the sensible thing would be on the target platform", rollover is probably just what you want.

Distinction between undefined, unspecified, and implementation-defined is already in ISO C99 specification and is rather specific:

"NOTE: Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (...), to terminating a translation or execution (...)."

> which is more like "do whatever the sensible thing would be on the target platform"

That is a meaning of 'implementation-defined' in C parlance.

Re: C23 Implications for C Libraries

#128
post #90

Earlier quoted context omitted.

My usages are similar to yours, but new C standards still benefit me because I can opportunistically detect and make use of new features in a configure script. To use my baby as an example: free_sized(void *ptr, size_t alloc_size) is new in C23. I can detect whether or not it's available and use it if so. If it's not available, I can just fall back to free() and get the same semantics, at some performance or safety c…

The free_sized function is kind of a bad example, though. For years to come, using free_sized will break malloc interposition. Interposed mallocs will not support free_sized initially. (It's currently not in jemalloc, tcmalloc, mimalloc as far as I can see.) If we add it to glibc and your application picks it up, calls to free_sized will end up with the glibc allocator even if malloc/free/… have been interposed. Mayb…

> Maybe there is a way to paper over this in the glibc implementation of free_sized (rather than calling free unconditionally), and still do something useful for the glibc allocator. I don't know.

We emailed about this a little contemporaneously (thread "Sized deallocation for C", from February), and I think we came to the conclusion that glibc can make interposition work seamlessly even for interposed allocators lacking free_sized, by checking (in glibc's free_sized) if the glibc malloc/calloc/realloc has been called, and redirecting to free if it hasn't. (The poorly-named "Application Life-Cycle" section of the paper).

Re: C23 Implications for C Libraries

#129

Earlier quoted context omitted.

That's only true for the relatively recent and generally unhelpful "nasal demons" interpretation of undefined behavior; under the older concept, which is more like "do whatever the sensible thing would be on the target platform", rollover is probably just what you want.

Distinction between undefined, unspecified, and implementation-defined is already in ISO C99 specification and is rather specific: "NOTE: Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (...), to terminating a translation or execution (...)." > which is mor…

I am familiar with the verbiage in the specification. My contention is that the currently popular tendency for C compilers to generate code which behaves in ways that are absurd and unpredictable, on the grounds that you shouldn't have been doing that anyway, is an unhelpful indulgence on the part of the compiler engineers.

Re: C23 Implications for C Libraries

#130
post #51

Earlier quoted context omitted.

> Who exactly are these new C-standards for? An example: The C11 memory model + + many compilers supporting C11 has/had a positive impact on language runtimes. Portable CAS! > If your team is up-to-date enough to quickly adopt C23, then why not just use Rust or (heaven forbid, C++23)? Another example: If you're programming e.g. non-internet-connected atomic clocks with weather sensors like those produced by La Crosse…

Atomic is one of the few things in C11 I like most. Unfortunately, it is an optional feature along with threading [1]. It is not portable. In the end, I am still using gcc/clang's __sync or __atomic builtins. [1] https://en.wikipedia.org/wiki/C11_(C_standard_revision)#Opti...

> Unfortunately, it is an optional feature along with threading [1]. It is not portable.

Portability isn't binary. It's the result of work being done behind-the-scenes to provide support for a common construct on a variety of hardware and operating systems. It's a spectrum.

GCC certainly is portable, but it doesn't support every ISA and OS. Over time it has even dropped support for several.

Random thoughts since I'm still in the process of waking up…

1. Most of is optional

2. long is 64 bits on Tru64 Unix which is valid under all versions of the standard

Post reply on HN