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.
A Defer Mechanism for C
41–50 of 248 posts
Re: A Defer Mechanism for C
#42I’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.
Re: A Defer Mechanism for C
#43Despite 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,…
Re: A Defer Mechanism for C
#44The best way to think about defer is that all the deferred statements are put in a goto label at the end of the block. When you break/return/whatever, it just jumps to that label first. This just makes slightly more convenient what the standard approach to error handling in C systems programming already is. Looking at the article, this specific implementation doesn’t quite go all the way, requiring a special guard {}…
How can you get away from having an explicit guard block? Without one, you couldn't 'defer' to the end of a containing block from within an if/while/do/for/etc. block. When/where the deferred code is executed has to be specified some way so an explicit marker for the defer 'scope' is surely required without severely limiting the utility of the feature.
guard {
void *ptr = malloc(12);
if (ptr) {
defer free(ptr);
// Use ptr
}
// Use ptr some more
} // free ptr here
Without guard keyword: {
void *ptr = malloc(12);
defer { if (ptr) free(ptr); }
if (ptr) {
// Use ptr
}
// Use ptr some more
} // free ptr hereRe: A Defer Mechanism for C
#45I’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.
defer is great for many use cases, available in Go, Swift and other languages, and nothing like a kludge. If anything RAII is unfit for C (which doesn't have classes), and in itself, a kludge (it's an idiom, not a language feature).
In terms of usability, destructors allow for resource management that is far easier at the call site than any other language. "with" blocks such as in python require the call site to be modified to include the explicit time of destruction, whereas C++ gets that for free from its existing scoping rules. "try/finally" such as in Java also requires modifying the call site, but at least has reasonable default behavior if accidentally omitted. "defer" feels like it has the worst of both worlds. It requires the call site to be modified when a resource is owned, and also requires the caller to know what the corresponding cleanup function is for any allocation.
Re: A Defer Mechanism for C
#46 guard {
for (int i = 0; i
Now the compiler has to:1. implement some side of capture/closure mechanism to keep all the 'i's to the end of the guard block
2. do dynamic allocation to store the closures so they can be executed at the end did the scope
1 seems like too much work for such a feature, and 2 is a massive no. Implicit dynamic allocation, in C?
And all of this for nothing. The guard syntax doesn't give any reasonable benefits. They should have just kept it simple; defer happens at the end of the scope, and it just takes 'i' by "reference". It's a shame because it's a feature I would really like to have.
Re: A Defer Mechanism for C
#47Earlier quoted context omitted.
Destructors are not called randomly.
"Smart pointers go brr" It's not really random, but it's quite hard to follow.
(std::shared_ptr should be used only when absolutely required and should be kept under close watch the whole time.)
Re: A Defer Mechanism for C
#48Despite 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,…
What is "I am thinking of using C?"
Re: A Defer Mechanism for C
#49Re: Should object values be captured? The results from 387 responses (to a Twitter poll) show a 2:1 preference for the value being read at the time the deferred statements are executed (66.9%) rather than when the defer statement encountered(33.1%). Since both options - by value and by reference - may be viewed as reasonable or desirable, neither should be a default. Instead, they both should be using a special synta…
If they add this, it would be better to restrict it to the current scope, to avoid forcing the language to create complexity to handle defers created via loop in the background.
Of course, that leads to the question of what to do when you loop over a defer with a goto, which would make sense if you were constantly appending function pointers and arguments to the frame similar to alloca.
That could lead to fun things like a function getting inlined into a for loop and then having its defers that would have been in function instead piled together to blow the stack.
They'll have to make sure they account for that in the spec and implementations.
Mostly, it would be easier to remember that C should not be using such a pattern, and that if you have need of defers and various similar magic to be baked into the language and compiler, what you're doing is probably inappropriate for implementation in the C language in the first place.
Re: A Defer Mechanism for C
#50The best way to think about defer is that all the deferred statements are put in a goto label at the end of the block. When you break/return/whatever, it just jumps to that label first. This just makes slightly more convenient what the standard approach to error handling in C systems programming already is. Looking at the article, this specific implementation doesn’t quite go all the way, requiring a special guard {}…
Dlang already has scope guards (Appendix C in the OP) https://dlang.org/spec/statement.html#scope-guard-statement, and does so at block scope. For some code it's a more elegant solution (keeps acquire and release code close together), without introducing the usual C++ RAII issues.