7 ms·
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 c
by CyberRabbi 6y ago
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.
- kangalioo 6y agoDefer is more explicit than RAII, so a better fit for the very explicit C languag
- kangalioo 6y agoDefer is more explicit than RAII, so a better fit for the very explicit C language
- CyberRabbi 6y agoIt’s even more explicit to just call your cleanup routines manually, so by that logic “defer” is inferior to existing methods of handling cleanup in C
- gpderetta 6y agosubroutine calls requires implicit allocation and deallocation of stack frames. Real Programmers™ use goto and manage the stack by hand.
- drsozesakamoto 6y ago> subroutine calls requires implicit allocation and deallocation of stack frames. Real Programmers™ use goto and manage the stack by hand. Could u point to an example of programmers doing this ?
- gpderetta 6y agosorry, I had forgotten the /sarcasm tag. Although I guess Cheney on the MTA counts.( https://dl.acm.org/doi/10.1145/214448.214454 https://dl.acm.org/doi/10.1145/214448.214454 )
- coldtea 6y agodefer 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).
- CyberRabbi 6y agoWhat if you forget to call “defer”? Then your code is incorrect. That’s kludgy in comparison to RAII where it’s impossible to forget to call a destructor.
- coldtea 6y agoThe whole point is that it's much easier to NOT forget defer (which goes right after the resource acquisition line), than to forget to free the resource (which happens much further down the function). So it's immediately better compared to the current C situation. As for compared to RAII? Well, thats one failure mode for defer (forgetting it), whereas there are dozens of ways to mess RAII...
- CyberRabbi 6y agoI made no comparison between “defer” and the current C situation. In comparison to RAII, “defer” as a language feature is a kludge. Mainly because RAII completely solves the problem of correct resource cleanup for API users while “defer” does not.
- coldtea 6y agoRAII is an idiom, not a language feature. Destructors might be the language feature, but they have their own issues and caveats. So I don't see the comparison...
- isogon 6y agoI think it's quite reasonable to compare defer and destructors, in that case. Destructors probably cannot be usefully imported into C while preserving the simplicity of the language: then you'll want at least unique_ptr to manage your memory with destructors, then probably shared_ptr, and some ownership semantics as you pass those around, et cetera. In that sense, defer strikes a balance between simplicity and usefulness. However, there is still a comparison.
- Thaxll 6y agoAlso defer runs even if your code panic which is great.
- jdright 6y agoExactly. I always explain this but people tend to ignore and not see how error prone defer is. It is a shame that a kludge (ugly hack actually) like this receives so much praise.
- yason 6y agoRAII is a special case of defer, due to how it abuses constructors and destructors to hook into the points of entering and exiting scope. You could write a RAII implementation in terms of defer but not the other way around. RAII doesn't help with a generic pair of init and deinit functions, such as malloc() and free() for example, unless you wrap your mallocs into "memory objects" or something. You can't do anything with RAII unless you wrap your stuff into objects which just forces the OO crap on everything regardless of whether it's a good fit for the OO paradigm. But even in RAII, classes are merely just a way to bind init and deinit together. As a result, you can't "forget" to free the resource. (Unless you use the new operator...) But this is merely an interface issue: defer could be of the form void *block = defer malloc(SZ) with free(block); or something similar that requires the init and deinit calls to be part of the defer expression itself. Nevertheless, a defer is clearly a useful language feature that C actually lacks. Currently C doesn't offer the code any attaching points to the lexical scope of the program. You can fake it with a special for(;;) statement but it's a kludge and even by wrapping it into a macro it's very hard to make it a generic solution.
- gpderetta 6y ago> RAII doesn't help with a generic pair of init and deinit functions, such as malloc() and free() for example, people have been writing RAII scope_exit classes for at least 20 years to do exactly this. > You can't do anything with RAII unless you wrap your stuff into objects which just forces the OO crap on everything regardless of whether it's a good fit for the OO paradigm. wrapping something in an object does not make it OO. For example there is nothing object oriented about std::unique_ptr.
- saagarjha 6y agoWell, you can only wrap objects in one, although you can "wrap" a primitive by writing lambdas for this purpose.
- jcelerier 6y ago> You could write a RAII implementation in terms of defer but not the other way around. c'mon, here's the article from 2000 that introduces ScopeGuard : https://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758?pgno=2 https://www.drdobbs.com/cpp/generic-change-the-way-you-write...
- cesarb 6y ago> Then again, nearly none of the syntactic C features post-C89 have been very compelling or widely adopted. That's Microsoft's fault; it's 2020 already, and unless things changed since I last looked, their compiler still doesn't have full support for the C99 standard. Even then, some of the C99 syntactic features have been somewhat widely adopted (at least when not compiling for Windows); off the top of my head, we have "//" comments, declarations in the middle of a block, and designated initializers.
- pjmlp 6y agoThey fully support C11 and C17 now. Everything that was moved into optional in C11, like VLAs, is not planned to ever be supported.
- CyberRabbi 6y ago“Somewhat widely adopted” is not “widely adopted” :) I see people tend to write C89+designated initializers but this is a code smell IMO. Initial data should always be 0, especially data that lives in BSS/data section.
- skohan 6y agoRAII 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.
- zelly 6y agothat's what arenas are for