Live data from Hacker News

C: Simple Defer, Ready to Use

gustedt.wordpress.com

51–60 of 157 posts

Re: C: Simple Defer, Ready to Use

#51

I really, really do not like what that could do to the readability of code if it was used liberally. It's like GOTOs, but worse, because it's not as visible. C++'s destructors feel like a better/more explicit way to handle these sorts of problems.

> I really, really do not like what that could do to the readability of code if it was used liberally.

> It's like GOTOs, but worse, because it's not as visible.

> C++'s destructors feel like a better/more explicit way to handle these sorts of problems.

But what C++ gives you is the same thing:

> It's like GOTOs, but worse, because it's not as visible.

!

The whole point of syntactic sugar is for the machinery to be hidden, and generated assembly will generally look like goto spaghetti even when your code doesn't.

What this implementation of defer does under the covers is not interesting unless you're trying to make it portable (e.g., to older MSVC versions that don't even support C99 let alone C23 or GCC local function extensions) or efficient (if this one isn't).

Re: C: Simple Defer, Ready to Use

#52
post #41

Earlier quoted context omitted.

GCC has the __cleanup__ attribute which works in conjunction with exceptions in C to provide an RAII mechanism.

No it doesn't; C functions don't set up appropriate registrations with the C++ exception / stack unwinding systems, thus C functions are simply skipped over on the way up towards the nearest exception handler. __attribute__((cleanup(…))) is purely a scope-local mechanism, it has absolutely nothing to do with exceptions.

"If -fexceptions is enabled, then cleanup_function is run during the stack unwinding that happens during the processing of the exception. Note that the cleanup attribute does not allow the exception to be caught, only to perform an action. It is undefined what happens if cleanup_function does not return normally."[1]

While it's true that it -fexceptions is disabled for C by default, some C libraries need to enable it anyway if they want to interact with C++ exceptions this way. For example C++ requires that qsort and bsearch propagate the exception thrown by the comparison callback normally, so libc implementations that are also used from C++ do enable it.

[1] https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attribute...

Re: C: Simple Defer, Ready to Use

#53

I'm a strong believer that if C had defer, many bugs would disappear. The number 1 issue I find myself having when switching from C++ to C is missing RAII (Main C++ way of implementing defer).

I agree about missing RAII when switching away from C++ but it seems like defer cleans up after enclosing function exits while RAII cleans up when object goes out of scope, which is more fine-grained. Maybe I'm misunderstanding exactly when defer would clean up but it seems more like a safety feature. As people pile more stuff into the function the cleanup would be deferred more and more while RAII encapsulates the m…

Yeah, defer within scope is the most ideal form in my opinion.

Re: C: Simple Defer, Ready to Use

#54
post #43
post #37

Earlier quoted context omitted.

To be fair you're not communicating very well — there are no trampolines being used here because the call site is directly in the same function, so no trampoline is needed with already being in the correct stack frame. (And also on -O1 and higher the entire call is optimized out and the nested function inlined instead.)

Fair, I was not explaining why the statement was wrong. Anyhow, the trampoline is not related to the call site being in the same function but whether a pointer is generated to the nested function and escapes. Nested functions in general do not need trampolines or executable stack.

Nice, if this is reliable across gcc versions and optimization levels, I might consider it for future stuff. Though making it such that treesitter and other tools dont barf on it would still need investigation.

Re: C: Simple Defer, Ready to Use

#55
post #43
post #37

Earlier quoted context omitted.

To be fair you're not communicating very well — there are no trampolines being used here because the call site is directly in the same function, so no trampoline is needed with already being in the correct stack frame. (And also on -O1 and higher the entire call is optimized out and the nested function inlined instead.)

Fair, I was not explaining why the statement was wrong. Anyhow, the trampoline is not related to the call site being in the same function but whether a pointer is generated to the nested function and escapes. Nested functions in general do not need trampolines or executable stack.

And I should mention that GCC nowadays can also allocate the trampoline on the heap: -ftrampoline-impl=heap

Re: C: Simple Defer, Ready to Use

#57
post #41

Earlier quoted context omitted.

GCC has the __cleanup__ attribute which works in conjunction with exceptions in C to provide an RAII mechanism.

No it doesn't; C functions don't set up appropriate registrations with the C++ exception / stack unwinding systems, thus C functions are simply skipped over on the way up towards the nearest exception handler. __attribute__((cleanup(…))) is purely a scope-local mechanism, it has absolutely nothing to do with exceptions.

GCC has comon exception handling across its supported languages. They have exceptions as a C extension that interoperate with C++. Cleanups get called during a stack unwind because they are considered the same as a destructor.

Re: C: Simple Defer, Ready to Use

#58

I really, really do not like what that could do to the readability of code if it was used liberally. It's like GOTOs, but worse, because it's not as visible. C++'s destructors feel like a better/more explicit way to handle these sorts of problems.

How do you write C code that needs to do this (set up several resources, and clean only some of them up depending on where the function returns) so that it’s easy to follow?
Post reply on HN