Live data from Hacker News

Tell HN: C Experts Panel – Ask us anything about C

news.ycombinator.com

811–820 of 978 posts

Re: Tell HN: C Experts Panel – Ask us anything about C

#811

Earlier quoted context omitted.

Most of the useful optimizations that could be facilitated by treating integer overflow as jump the rails optimization could be facilitated just as well by allowing implementations to behave as though integers may sometimes, non-deterministically, be capable of holding values outside their range. If integer computations are guaranteed never to have side effects beyond yielding "weird" values, programs that exploit th…

How is this better behavior?

Many programs are subject to two constraints:

1. Behave usefully when practical, if given valid data.

2. Do not behave intolerably, even when given maliciously crafted data.

For a program to be considered usable, point #1 may be sometimes be negotiable (e.g. when given an input file which, while valid, is too big for the available memory). Point #2, however, should be considered non-negotiable.

If integer calculations that overflow are allowed to behave in loosely-defined fashion, that will often be sufficient to allow programs to meet requirement #2 without the need for any source or machine code to control the effects of overflow. If programmers have to take explicit control over the effects of overflow, however, that will prevent compilers from making of the any useful overflow-related options that would be consistent with loosely-defined behavior.

Under the kind of model I have in mind, a compiler would be allowed to treat temporary integer objects as being capable of holding values outside the range of their types, which would allow a compiler to optimize e.g. x*y/y to x, or x+y>y to x>0, but the effects of overflow would be limited to the computation of potentially weird values. If a program would meet requirements regardless of what values a temporary integer object holds, allowing such objects to acquire such weird values may be more efficient than requiring that programs write code to prevent computation of such values.

Re: Tell HN: C Experts Panel – Ask us anything about C

#812
post #810

I want this feature in the standard. If there exists any memory block allocated using malloc() / calloc() / realloc() which has not been free()'d, at the end of the program, they would be free()'d automatically. One can easily do it with keeping a linked list and using atexit(), but, can it be added to the standard? A general question, will anything, any feature, which is "easy" to implement in pure C, like array kno…

The operating system handles this for you on process deletion. Lots of “one shot” programs count on this (and (e.g.) file descriptors being automatically closed).

Re: Tell HN: C Experts Panel – Ask us anything about C

#813
post #812
post #810

I want this feature in the standard. If there exists any memory block allocated using malloc() / calloc() / realloc() which has not been free()'d, at the end of the program, they would be free()'d automatically. One can easily do it with keeping a linked list and using atexit(), but, can it be added to the standard? A general question, will anything, any feature, which is "easy" to implement in pure C, like array kno…

The operating system handles this for you on process deletion. Lots of “one shot” programs count on this (and (e.g.) file descriptors being automatically closed).

So, should I not care about that so much, and write programs without free()'ing allocated memory?

If OSes do that, why not standardize that in C?

Re: Tell HN: C Experts Panel – Ask us anything about C

#814
post #416

Earlier quoted context omitted.

>There have been no proposals to add new array types and it doesn't seem likely at the core language level. One alternative to adding types is to allow enforcing consistency in some structs with the trailing array: struct my_obj { const size_t n; //other variables char text[n]; }; where for simplicity you might only allow the first member to act as a length (and it must of course be constant). The point is that then…

What should happen if you reassign the object?

What do you mean "reassign"?

You can't reassign the length variable since it's marked `const`. You should see something like "warning: assignment discards `const` qualifier from pointer target type" if you pass it to `realloc`, which tells you that you're breaking consistency (I guess this might be UB). You could write `vrealloc` to allow resizing such structs, which would probably be called like:

    my_obj *tmp = vrealloc(obj, sizeof(obj), sizeof(obj->text), obj->n, newsize);

Re: Tell HN: C Experts Panel – Ask us anything about C

#815

Earlier quoted context omitted.

This sounds like something memcpy would do already for you?

A 36-bit system with (it sounds like) 9-bit bytes stores bit 8 of a int in bit 8 of a char, and bit 9 of the int in bit 0 of the next char; memcpy won't change that. They're asking for somthing like: unsigned int x = in[0] + 512*in[1] + 512*512*in[2] + 512*512*512*in[3]; /* aka x = *(int*)in */ out[0] = x & 255; x>>=8; out[1] = x & 255; x>>=8; out[2] = x & 255; x>>=8; out[3] = x & 255; /* *not* aka *(int*)out = x */

Ah, I see.

Re: Tell HN: C Experts Panel – Ask us anything about C

#816
post #814

Earlier quoted context omitted.

What should happen if you reassign the object?

What do you mean "reassign"? You can't reassign the length variable since it's marked `const`. You should see something like "warning: assignment discards `const` qualifier from pointer target type" if you pass it to `realloc`, which tells you that you're breaking consistency (I guess this might be UB). You could write `vrealloc` to allow resizing such structs, which would probably be called like: my_obj *tmp = vreal…

What would you do with the old text? Delete it?

Re: Tell HN: C Experts Panel – Ask us anything about C

#817
post #410

Earlier quoted context omitted.

Well, I am informally proposing making those standard :-). IMO they're a lot more ergonomic than the Annex K functions, and do the thing most programmers think the strncat/strncpy functions do (admittedly, not part of ISO C). Annex K should be forgotten as the mistake it is and we can move on with existing real-world interfaces instead of inventing features from whole-cloth. I thought that was generally the C standar…

I disagree, because they return a value that nobody really wants and thus perform poorly: https://saagarjha.com/blog/2020/04/12/designing-a-better-str...

So standardize them as returning void — great!

Re: Tell HN: C Experts Panel – Ask us anything about C

#818
post #566
post #403

Earlier quoted context omitted.

Probably link libicu rather than rely on libc.

libicu is a 40MB mess where you need only 5Kb of it. Only case folding and one normalization is needed, with tiny tables. Additionally the used UNICODE_MAJOR and _MINOR are needed. They are always years behind, and you never know which tables versions are implemented.

  -Wl,--gc-sections

Re: Tell HN: C Experts Panel – Ask us anything about C

#819
post #242

Earlier quoted context omitted.

Golang gets this wrong. It should be scope-level not function-level (or perhaps there should be two different types, but I have never personally had a need for a function-level cleanup). Edit: Also please review how attribute cleanup is used by existing C code before jumping into proposals. If something is added to C2x which is inconsistent with what existing code is already doing widely, then it's no help to anyone.

Yes, we have discussed adding this feature at scope level. A not entirely serious proposal was to implement it as follows: #define DEFER(a, b, c) \ for (bool _flag = true; _flag; _flag = false) \ for (a; _flag && (b); c, _flag = false) int fun() { DEFER(FILE *f1 = fopen(...), (NULL != f1), mfclose(f1)) { DEFER(FILE *f2 = fopen(...), (NULL != f2), mfclose(f2)) { DEFER(FILE *f3 = fopen(...), (NULL != f3), mfclose(f3))…

Apropos of this, I'll toss in: please support do-after statements (and also let statements).

  do foo(); _After bar();
  /* exactly equivalent to (with gcc ({})s): */
  ({ bar(); foo(); });
  #define DEFER(a, b, c) \
    _Let(a) if(!b) {} else do {c;} _After
(This is in fact a entirely serious proposal, though I don't actually expect it to happen.)

Re: Tell HN: C Experts Panel – Ask us anything about C

#820
post #382

Earlier quoted context omitted.

Annex K isn't being adopted because it's unergonomic and doesn't solve the problem it purports to. Even the proposer (Microsoft) does not actually implement Annex K as specified in the ISO.

Microsoft originally implemented the Annex K Bounds checked interfaces (e.g., the *_s functions) back in the 1990s in response to well-publicized vulnerabilities. They proposed standardization to the C Standards committee. The committee made many changes to the proposal, possibly going too far away from the original implementation. During this time, I would say that Microsoft was very differential to the wishes of th…

I think we are in agreement that Microsoft does not implement Annex K as specified in ISO C. I don't fault them for that; I wouldn't either.

As to unergonomic, that's somewhat subjective. But I'm a long-time C practitioner and that's my feel of the API. Constraint handlers are a mistake. Ambient state that is not part of the function interface, as well as asynchronous interaction, make for poor APIs. Constraint handlers are a mismatch for library use of safe functions, as well as kernel environments.

Most functions seem pointless; e.g., snprintf_s. Re-adding gets() in the form of gets_s() seems unhelpful. Why bsearch_s, qsort_s, memcpy_s/memmove_s?? Do you really think strerror_s() is useful? Or strnlen_s()?

Post reply on HN