Defer: Resource cleanup in C with GCCs magic

oshub.org

55 points by joexbayer a day ago


babel_ - 9 hours ago

Testing with Jen's macro this was based on, and found that the always_inline was redundant under even -O1 (https://godbolt.org/z/qoh861Gch via the examples from N3488 as became the baseline for the TS for C2y, which has recently a new revision under N3687), so there's an interesting trade-off between visibly seeing the `defer` by not not-inlining within the macro under an -O0 or similar unoptimised build, since with the inlining they are unmarked in the disassembly. But, there's an interesting twist here, as "defer: the feature" is likely not going to be implemented as "defer: the macro", since compilers will have the keyword (just `defer` in TS25755, or something else that uses a header for sugared `defer`) and may see the obvious optimised rewrite as the straightforward way of implementing it in the first place (as some already have), meaning we can have the benefit of the optimised inline with the opportunity to also keep it clearly identifiable, even in unoptimised and debug builds, which would certainly be nice to have!

scoopr - 11 hours ago

Then there is the proposal to add standard `defer` to C2y[0]

[0] https://thephd.dev/c2y-the-defer-technical-specification-its...

majke - 9 hours ago

Nested functions are cool, although not supported by clang.

However they rely on Trampolines: https://gcc.gnu.org/onlinedocs/gccint/Trampolines.html

And trampolines need executable stack:

> The use of trampolines requires an executable stack, which is a security risk. To avoid this problem, GCC also supports another strategy: using descriptors for nested functions. Under this model, taking the address of a nested function results in a pointer to a non-executable function descriptor object. Initializing the static chain from the descriptor is handled at indirect call sites.

So, if I understand it right, instead trampoline on executable stack, the pointer to function and data is pushed into the "descriptor", and then there is an indirect call to this. I guess better than exec stack, but still...

lionkor - 3 hours ago

Slightly off-topic, but:

The fact that go "lifts" the deferred statement out of the block is just another reason in the long list of reasons that go shouldn't exist.

Not only is there no protection against data-races (in a language all about multithreading), basically no static checking for safety, allocation and initialization is easy to mess up, but also defer just doesn't work as it does in C++, Rust, Zig, and any other language that implements similar semantics.

What a joke.

letmetweakit - 10 hours ago

I'm always suspicious of exotic features that could fail in surprising ways.

joexbayer - a day ago

Small blog post exploring a defer implementation using GCC’s cleanup + nested functions, looking at the generated assembly and potential use cases.

pwdisswordfishz - 11 hours ago

I don't understand why people insist on simulating a poor substitute for RAII with a feature that is itself almost decent RAII.

> If malloc fails and returns NULL, the cleanup function will still be called, and there’s no simple way to add a guard inside free_ptr.

free(NULL) is a no-op, this is a non-issue. I don't know what's so hard about a single if statement anyway even if this were an issue.

KingLancelot - 5 hours ago

[dead]

mgaunard - 9 hours ago

Just use C++, it's its main feature on top of C.

grodes - 11 hours ago

Seems good, but I do not care about cleanup memory since I started to use arenas.