Live data from Hacker News

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

news.ycombinator.com

841–850 of 978 posts

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

#841
post #409

Earlier quoted context omitted.

typedef struct {uint8_t *data; size_t len;} ByteBuf; is the first line of code I write in a C project.

Could you add some extra information why this is so helpful or handy to have? Think it will benefit readers that are starting out with C etc.

In C, dynamically-sized vectors don’t carry around size information with them, often leading to bugs. This struct attempts to keep the two together.

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

#842

Earlier quoted context omitted.

The problem in practice is that you do not write “hello” and “world” to the destination buffer. You write data that is computed more or less directly from user inputs. Often a malicious user. So the user only needs to find a way to make the data longer than the developer expected. This may be very simple: the developer may have written a screensaver to accept 20 characters for a password, because who has a longer pas…

I think sprintf and gets can be perfectly secure interfaces. The standard just needs to specify them in a way that causes overflows to raise signals. This is probably more for POSIX and UNIX, since I think it requires the concept of memory mappings. For example: Start by specifying that memcpy goes by increasing address. This can be done by specifying that no pages to be written by memcpy can be written to until afte…

Surely you don’t expect every stack buffer to have a hard page placed after it to protect from overflows?

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

#843

Earlier quoted context omitted.

Maybe someone else can respond to this as well, but I feel like the primary reason signed overflow is still undefined behavior is because so many optimizations depend upon the undefined nature of signed integer overflow. My advice has always been to use unsigned integer types when possible. Personally, I would like to get rid of many of the trap representations (e.g., for integers) because there is no existing hardwa…

> My advice has always been to use unsigned integer types when possible. Unsigned types have their own issues, though: they overflow at "small" values like -1, which means that doing things like correctly looping "backwards" over an array with an unsigned index is non-trivial. > On the other hand, I just wrote a proposal to WG14 to make zero-byte reallocations undefined behavior that was unanimously accepted for C2x.…

realloc(foo, 0) was changed to no longer free in C99. A rant on the subject: https://github.com/Tarsnap/libcperciva/commit/cabe5fca76f6c3...

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

#844
post #817

Earlier quoted context omitted.

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!

What you really want is it to tell you how much it copied.

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

#845

Is memset(malloc(0), 0, 0) undefined behavior?

Let's assume the types have been corrected. malloc((size_t)0) behavior is defined by the implementation; there are two choices: (a) always returns a null pointer; or (b) acts like malloc((size_t)1) which can allocate or fail, and if it allocates then the program shall not try to reference anything through the returned non-null pointer. Now, memset itself is required (among other things) to be given as its first argum…

What observable difference is there between malloc(0) and malloc((size_t)0)?

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

#846

Earlier quoted context omitted.

Let's assume the types have been corrected. malloc((size_t)0) behavior is defined by the implementation; there are two choices: (a) always returns a null pointer; or (b) acts like malloc((size_t)1) which can allocate or fail, and if it allocates then the program shall not try to reference anything through the returned non-null pointer. Now, memset itself is required (among other things) to be given as its first argum…

What observable difference is there between malloc(0) and malloc((size_t)0)?

None.

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

#847

Earlier quoted context omitted.

What observable difference is there between malloc(0) and malloc((size_t)0)?

None.

I agree but he said the types needed to be corrected. As far as I know the types were already correct.

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

#848
post #793

Earlier quoted context omitted.

My idea was to add something like the GoLang defer statement to C (as a function with some special compiler magic). The following is an example of how such a function could be used to cleanup allocated resources regardless of how a function returned: int do_something(void) { FILE *file1, *file2; object_t *obj; file1 = fopen("a_file", "w"); if (file1 == NULL) { return -1; } defer(fclose, file1); file2 = fopen("another…

Go-like defer() is easily implementable for C using the asm() keyword. Here's an example of how it can be done for x86: https://gist.github.com/jart/aed0fd7a7fa68385d19e76a63db687f...

That's quite an achievement, but you've got to realise that hacks which overwrite the stack return address are not maintainable and likely wouldn't work except for a narrow range of compilers (and even specific versions of those compilers with specific options). It also won't work with stack hardening.

Also it's function-level (like golang) not scope-level (like attribute cleanup). As argued elsewhere in the this thread, golang got this wrong.

Also also, overwriting the return address on the stack kills internal CPU optimizations that both Intel and AMD do for branch prediction.

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

#850
another proposal:

    _If, _Ifdef, _Ifndef
inside function macros

for example:

    #ifdef SOME_CONST
    #define WHATEVER(w, h, a, t, e, v, e, r) \
        ... common part ... \
        ... for SOME_CONST ... \
        ... common part continued ...
    #else
    #define WHATEVER(w, h, a, t, e, v, e, r) \
        ... common part ... \
        ... when SOME_CONST not defined ... \
        ... common part continued ...
    #endif
With _Ifdef, the above could be written like:

    #define WHATEVER(w, h, a, t, e, v, e, r) \
    ... common part ... \
    _Ifdef(SOME_CONST, \
        (... for SOME_CONST ...) , \
        (... when SOME_CONST is not defined ...)
    ) \
    ... common part continued ...
With these, one could also do:

    #define FACTORIAL(n) _If(n == 0, 1, (n) * FACTORIAL(n))
    int f = FACTORIAL(6);
turns into: int f = (6) * (5) * (4) * (3) * (2) * (1) * 1;

That would be very useful, I think. It might help with code duplication in function macros.

Maybe _Switch/_Case thereafter.

Post reply on HN