Defer might be better than nothing, but it's still a poor solution. An obvious example of a better, structural solution is C#'s `using` blocks.
using (var resource = acquire()) {
} // implicit resource.Dispose();
While we don't have the same simplicity in C because we don't use this "disposable" pattern, we could still perhaps learn something from syntax and use a secondary block to have scoped defers. Something like: using (auto resource = acquire(); free(resource)) {
} // free(resource) call inserted here.
That's no so different to how a `for` block works: for (auto it = 0; it < count; it++) {
} // automatically inserts it++; it < count; and conditional branch after secondary block of for loop.
A trivial "hack" for this kind of scoped defer would be to just wrap a for loop in a macro: #define using(var, acquire, release) \
auto var = (acquire); \
for (bool var##_once = true; var##_once; var##_once = false, (release))
using (foo, malloc(szfoo), free(foo)) {
using (bar, malloc(szbar), free(bar)) {
...
} // free(bar) gets called here.
} // free(foo) gets called here.
That is a different approach, but I don't think you've demonstrated why it's better. Seems like that approach forces you to introduce a new scope for every resource, which might otherwise be unnecessary:
Compared to: Of course if you want the extra scopes (for whatever reason), you can still do that with defer, you're just not forced to.