There's nothing implicit about defer.
There's nothing implicit about defer.
That's quite implicit. You can no longer reason about a local piece of code; you now have to know its lexical nesting up to top level to see if it's inside a guard block that might trigger hidden behavior.
Plus, to handle the free or the leak if you had forgotten to free a resource at the exit point would also require to "know its lexical nesting up to top level".
Between goto and longjump and co, C has much worse non-local behavior than defer.
By your definition only [1] "come from" would be non-local.
You can't goto out of a function, and you know there's exactly one such label inside it. If goto isn't local, then neither are function calls, since the function could be defined anywhere in the codebase.
You can with a goto expression and a label address available - though the behavior is undefined in C, so bets are off.
And you can with longjump/setjump more explicitly.
Anyway, what could possibly happen at the end of a while loop, besides going back to the begining for the test?
Besides, if you have a bug in your code, you will have to look at the whole block anyway.
You have to check every line of a while loop to know what’s going on. Heck, another thread could hold a pointer aliasing the loop variable and then mutate it, causing the loop to terminate for no obvious reason.
Which C doesn't have.
They are no less explicit than the actions performed at the end of iterations of for or while loops. In general, for C, understanding the behavior of code requires understanding “is it in a block, and if so what kind of block”; guard blocks would be not generally different.
However, for some things you can only free/return resources if you successfully created that resource. At which point you would need to use something like a stack.