Live data from Hacker News

Emulating Swift's “defer” in C, with Clang or GCC+Blocks

fdiv.net

1–10 of 33 posts

Re: Emulating Swift's “defer” in C, with Clang or GCC+Blocks

#3

The canonical method in C is to jump to a named label which hosts some functions to unwind/close any open descriptors or operations. As it involves the use of a goto statement, it drives certain people mad. I wasn't aware of C Blocks.

the problem with goto for error handling is possibility of programmer error: you have to keep track of the order of labels yourself, whereas defer does that for you. i won't comment on anti-goto fascism.

Re: Emulating Swift's “defer” in C, with Clang or GCC+Blocks

#4
Not the same semantics, as least compared to Golang. This is block-scoped, but "defer" in Go is function-scoped and has highly dynamic semantics—for example, call it in a loop and the compiler may not be able to statically prove how many times it will run.

(Note that, IMO, the semantics of the feature as implemented in the article are preferable to those of Golang, so I wouldn't personally go to the effort of trying to duplicate Go's behavior.)

Re: Emulating Swift's “defer” in C, with Clang or GCC+Blocks

#8

The canonical method in C is to jump to a named label which hosts some functions to unwind/close any open descriptors or operations. As it involves the use of a goto statement, it drives certain people mad. I wasn't aware of C Blocks.

Clang's blocks produce atrocious code. Look at the disassembly for:

    int main(){ __block int (^foo)(int x) = ^ int (int x) { if(x
versus the GCC:

    int main(){ int foo(int x) { if(x
if you want to see what I'm talking about.

CLANG: http://pastebin.com/37A9by4V

GCC: http://pastebin.com/RMEDnwxi

However, defer does look interesting, and implementing it for GCC is very easy:

    #define defer_(x) do{}while(0); \
            auto void _dtor1_##x(); \
            auto void _dtor2_##x(); \
            int __attribute__((cleanup(_dtor2_##x))) _dtorV_##x=69; \
            void _dtor2_##x(){if(_dtorV_##x==42)return _dtor1_##x();};_dtorV_##x=42; \
            void _dtor1_##x()
    #define defer__(x) defer_(x)
    #define defer defer__(__COUNTER__)
You don't have to use the stupid block-syntax either, just:

    in = fopen("whatever", "r");
    defer { fclose(in); }
Post reply on HN