Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Ugh.

Go's "defer" is reasonably clean because Go is garbage-collected. So you don't have to worry about something being deleted before a queued "defer" runs. That's well-behaved. This is going to be full of ugly, non-obvious problems.

Interestingly, it's not really "defer" in the Go sense. It's "finally", in the try/finally sense of C++, using Go-type "defer" syntax". This mostly matters for scope and ownership issues. If you want to close a file in a defer, and the file is a local variable, you have to be sure that the close precedes the end of block de-allocation. Most of the discussion in the article revolves around how to make such problems behave halfway decently.

"defer" happens invisibly, in the background. That's contrary to the basic simplicity of C, where almost nothing happens invisibly.



The point of defer is to put the cleanup logic in one place for local variables though, so the risk of someone else deleting it isn't a thing.


> It's "finally", in the try/finally sense of C++

What sense is that? C++ doesn't have finally and the article explicitly calls out how its not like destructors.


Right, C++ doesn't have "finally". But "defer" defers to when a "finally" section would run in a language that has it. I think.


That's what it does in Go too. This is totally defer in the Go sense (except they fixed the scoping issue).


Not quite. "The central idea behind defer is that, unlike its Go counterpart, defer in C is lexically bound, or “translation-time” only, or “statically scoped”"

Defer in Go puts the deferred action on a run time to-do list that's processed at function exit. You can queue up deferred actions from a loop in Go. Not in this proposal for C.

What happens in this C proposal if you put a defer request inside a loop? Is it a compile time error, do they somehow to try to give it meaningful semantics, or is it undefined behavior?


> What happens in this C proposal if you put a defer request inside a loop? Is it a compile time error, do they somehow to try to give it meaningful semantics, or is it undefined behavior?

The action runs at the end of the loop-body, before the next iteration. It does this because the loop-body is the enclosing block, and a defer will always run when its enclosing block ends. As described in the article, this is intentionally-so and makes it possible to acquire a mutex inside a loop while automatically releasing it before the next iteration, something which is easy to get wrong in Go.


Loops in C introduce a new lexical scope, so the defer runs once for every loop iteration.

Assuming you are using defer for destructor purposes, and use it where you declare your variable, this would generally be what you want, as it frees the memory at the same time it goes out of scope.

The flip side of this is that code like the following would be broken:

    char *foo = NULL;
    if (true) {
         foo = calloc(1,1);
         defer { free(foo); }
    }
    char c = *foo;
As foo gets freed at the end of the conditional, which is prior to the dereference.


That particular example is easy - just put the defer before the if.


Yes maybe you didn't get to the end of my one-sentence comment but I did say

> except they fixed the scoping issue

> What happens in this C proposal if you put a defer request inside a loop?

It executes at the end of the loop body.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: