Live data from Hacker News

A Defer Mechanism for C

gustedt.wordpress.com

201–210 of 248 posts

Re: A Defer Mechanism for C

#201
post #6
post #2

Despite being convenient,I have the feeling that it might be a bad idea. One of the key interest of C compared to more recent languages is that everything is explicit. With a finger you can follow the code as it runs and know exactly what is going on and when exactly. At the opposite, there is c++ that does a lot of things automagically. And it is often hard to understand why you suddenly get a segfault out of blue,…

> One of the key interest of C compared to more recent languages is that everything is explicit. There's nothing implicit about defer.

I think the broader and more accurate point is that defer adds cognitive load to reasoning about the order of execution. It's true that defer (at least everywhere I've seen it executed) is totally explicit and deterministic, but in the case of multiple defers in the same block it can take some thought to reason through exactly what happens when.

Re: A Defer Mechanism for C

#202

I’ve always considered “defer” an inelegant kludge in comparison to RAII for automatic cleanup of resources. It’s surprising that the C standards committee is considering adding that to the language. Then again, nearly none of the syntactic C features post-C89 have been very compelling or widely adopted.

RAII can be an anti-pattern for certain high performance applications. Yes a lot of times you want the assurance you're always dealing with properly initialized memory, but if you're really optimizing for memory performance (one of the jobs C is for) then a lot of times initializing and deinitializing small blocks of memory is exactly the opposite of what you want to do.

Re: A Defer Mechanism for C

#203

Earlier quoted context omitted.

Maybe, maybe not. If your context has a list of things to free, it can also have a list of things to close. Or whatever you want. Many libraries do stuff like this and call the context creation/deletion lib_init/ lib_shutdown.

It sounds an awful lot like such a context mechanism needs dynamic allocations. Something like the GNU cleanup attribute or a proposal like defer, or C++ RAII, can do that as a stack unwind, without the need for heap.

That would be the easiest way. Definitely a disadvantage

Re: A Defer Mechanism for C

#204
post #137
post #89

Earlier quoted context omitted.

Which is why we want it to be standardized. It's already widely used on Linux and BSDs, the big compilers already implement the underlying functionality (because it's needed by C++), GCC and LLVM implement the exact same extension in an identical way, it does everything that people need, so let's make it work officially.

Still there is a life beyond UNIX clones and gcc/clang. The C compiler vendor for some embedded CPU with homegrown C compiler for their in-house OS also has a seat at ISO table. While people here might not care, ISO does.

The proposals generally exist so that compiler vendors can comment on them and try proof-of-concept implementations if they're interested.

Re: A Defer Mechanism for C

#205

Earlier quoted context omitted.

> defer just changes the problem from forgetting to write free to forgetting to write defer. That's the case only the first time you write code: { foo *f = new_foo(); // step 1 /* lots of code */ // step 3 free(f); // step 2 } vs { foo *f = new_foo(); // step 1 defer free(f); // step 2 /* lots of code */ // step 3 } Sure, in both cases you can forget step 2. But what about review ? With defer, the init and cleanup co…

I think this example demonstrates the opposite of what you intended. Defer doesn't give you anything that you can't already do. In your last four code blocks, you demonstrated three alternate ways to implement the functionality you want without defer. Defer is just a slightly different, arguably nicer fourth way to implement the same code. Language features should be orthogonal. A new language feature should add some…

> In your last four code blocks, you demonstrated three alternate ways to implement the functionality you want without defer.

My, I didn't think it was possible to miss the point like that. Are you even arguing in good faith? Let's examine for a moment the 3 other alternatives.

First, we get the "repeat ourselves" problem: when I have several exit points, I must clean up at each exit. And if I edit the code in any way, (for instance by adding yet another check), I must review everything that has been initialised until this point and clean it up there again. This might be okay if I have only 1 or 2 exit points, but if I have more this is clearly unacceptable.

Second, we have goto. We replace our exit points by a goto cleanup. That one at least can scale. I don't like it however for three reasons. First, the cleanup code is at the end, far from the init code, so checking that the two pairs together correctly is inconvenient. Second, I need to manage an additional variable for the return value. Third, goto is banned in a lot of places, no matter how convoluted the alternatives may be.

Third, we have this monstrous pyramid if else that wastes horizontal space, requires you to re-indent everything at the slightest edit, separates cleanup code from init code, and is just plain ugly. The only thing going for it is the single exit point, and frankly it isn't much.

---

Those "alternatives" are anything but. They're what we have to do when faced with a limited language that doesn't express what we want to say. Workarounds, not solutions.

> minor syntax adjustments

Your perspective must be seriously warped if you're calling the function-wide reorganisation I spoke of "minor syntax adjustments". Or you're not arguing in good faith.

> The real answer to "why defer?", of course, is that the authors need it to implement panic/recover.

That is a separate point, which I think I agree with. Me, I just want a way to trigger an instruction when we exit the current scope. It's the necessary complement to `break` and `return`, which provide ways to exit scope before the end of the block. We could get rid of them, and apply a straightjacket structured programming discipline of course, but personally, I don't think I'm ready to give up on `break` and `return`.

Re: A Defer Mechanism for C

#206

Earlier quoted context omitted.

I believe the situation is the same in C++, that is, if you have a shared_ptr cycle, the destructor will never be called, no? It is more deterministic in C++, but you can still call exit(). (which is even more straightforward than the refcount cycle)

> I believe the situation is the same in C++, in the specific case of shared_ptr, which are a small part of codebases, if they are even used - for instance an immense amount of C++ GUI programs use Qt which doesn't use shared_ptr-like ownership semantics but instead a tree-of-objects model which does not have this issue. In contrast in Java / C# any object that has a reference to another is at risk.

Sure. That’s why I said “more deterministic.” But even a rare event disproves the guarantee.

Re: A Defer Mechanism for C

#207
post #2

Despite being convenient,I have the feeling that it might be a bad idea. One of the key interest of C compared to more recent languages is that everything is explicit. With a finger you can follow the code as it runs and know exactly what is going on and when exactly. At the opposite, there is c++ that does a lot of things automagically. And it is often hard to understand why you suddenly get a segfault out of blue,…

Despite being convenient, I have the feeling that it might be a bad idea.

Probably. It's one of Go's lesser ideas.

C already has a "defer" mechanism in "exit", to close out files and such. Of course, the final I/O status gets lost.

Re: A Defer Mechanism for C

#208
post #2

Despite being convenient,I have the feeling that it might be a bad idea. One of the key interest of C compared to more recent languages is that everything is explicit. With a finger you can follow the code as it runs and know exactly what is going on and when exactly. At the opposite, there is c++ that does a lot of things automagically. And it is often hard to understand why you suddenly get a segfault out of blue,…

> One of the key interest of C compared to more recent languages is that everything is explicit. With a finger you can follow the code as it runs and know exactly what is going on and when exactly.

I don't agree! There's a lot of behavior that's implicit and you essentially need to internalize the C standard/compiler behavior to follow. Weak typing, for instance; defaults for memory access/fencing, handling faults, runtime semantics with respect to initialization of the process, cleanup via atexit, and signal handling.

Memorable, sure, but hardly explicit.

Re: A Defer Mechanism for C

#210

What does this offer that couldn't be accomplished with well placed goto's like in this example https://vilimpoc.org/research/raii-in-c/ (yes I get that defer > raii, but the question is meant to be more general)

hm, ok, they address this in the paper. "This code [i.e. goto-error-handling] has the advantage of making the conditional error handling code explicit but at the cost of proximity; the cleanup code is removed from where its need arises. This linearization requires a naming convention for the labels [...]"
Post reply on HN