[HN Gopher] Braiding the spaghetti: implementing defer in the pr...
       ___________________________________________________________________
        
       Braiding the spaghetti: implementing defer in the preprocessor
        
       Author : ingve
       Score  : 34 points
       Date   : 2024-09-12 10:56 UTC (4 days ago)
        
 (HTM) web link (gustedt.wordpress.com)
 (TXT) w3m dump (gustedt.wordpress.com)
        
       | pif wrote:
       | If you want to use RAII in C, just use the "cleanup" attribute of
       | gcc.
       | 
       | https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attribute...
        
         | wffurr wrote:
         | *in non portable non standard C
        
           | gobblegobble2 wrote:
           | Supported by both gcc and clang, so portable enough for most
           | people. I also like glib's cleanup attribute wrappers:
           | https://docs.gtk.org/glib/auto-cleanup.html.
        
           | wyldfire wrote:
           | It is non portable, that's true. But defer [1] is at least
           | undergoing discussions w/the standard committee. Didn't make
           | it into C23 but maybe next time.
           | 
           | [1] https://www.open-
           | std.org/jtc1/sc22/wg14/www/docs/n2895.htm
        
         | gustedt wrote:
         | That's not very practical if you have several operations to
         | perform, you'd have to create a specialized function each time.
         | So no, that extension is not an alternative to designing a new
         | flow control feature. (And it is not new, other languages have
         | it already.)
        
       | teo_zero wrote:
       | How would the proposed solution work with this code?
       | void foo() {         char *p = malloc(...);         defer
       | free(p);         ...         {           FILE *p = fopen(...);
       | defer fclose(p);           ...         }         return;       }
       | 
       | Would it run both deferred statements, each with the correct
       | argument?
        
         | gustedt wrote:
         | Yes, the visibility rules for variables remain exactly the
         | same. The dependent statement of a defer lives in the same
         | scope as the defer is placed.
        
       | aedrax wrote:
       | shameless plug for my defer header:
       | https://github.com/aedrax/defer.h
        
       | andrewla wrote:
       | I love the idea of having a defer statement in general for C, but
       | given the complexity of C scopes it's a little hard to wrangle
       | (switch statements in particular break a lot of assumptions about
       | how scopes should work).
       | 
       | I would prefer a directly scoped syntax similar for a for
       | statement, something like                  defer (void * p =
       | malloc(17); free(p)) {          ...        }
       | 
       | This gets more cumbersome as you have more such scopes in a
       | function, but it gives a sane bounding. You can sort of do this
       | now with a properly constructed for loop so that it cleans up on
       | regular exit from the loop, but it can't handle exception exits
       | (returns, breaks, and god forbid goto or longjmp).
        
         | gustedt wrote:
         | This would be much more restrictive that what is proposed,
         | because usually you would add `defer` statements as you go in a
         | block, when you allocate more resources for example.
         | 
         | Also usually you should be able to have several actions,
         | defer {          one;          two;        }
         | 
         | And the bounding in the proposed feature is sane, I think, it
         | is the surrounding compound statement (AKA `{ ... }` block).
        
       | sirwhinesalot wrote:
       | You can implement an acceptable defer with the standard
       | preprocessor and some switch abuse.
       | 
       | The only annoying part is needing to use "defer_return" and such
       | instead of the proper keywords.
       | 
       | Unlike most defer implementations for C this doesn't need a
       | function-scope fixed sized block, it's all properly scoped, the
       | switch effectively models a state machine. Similar tricks can be
       | used to implement yield and such.
        
       | sim7c00 wrote:
       | the amount of effort going into people either:
       | 
       | - straightup forgetting to free shit - writing horrible to read
       | code making it impossible to do cleanup or track allocations
       | 
       | why try to make c into c++ or rust? those languages already
       | exist.
        
       ___________________________________________________________________
       (page generated 2024-09-16 23:01 UTC)