User: Password:
Subscribe / Log in / New account



Posted Mar 5, 2014 17:36 UTC (Wed) by bronson (subscriber, #4806)
In reply to: RAII in C by tjc
Parent article: A longstanding GnuTLS certificate validation botch

Yeah! If they're talking about this:

    void cleanup_file(FILE **fp)
        // handle a bunch of boundary conditions, probably using global variables

     int main() {
         FILE *fp __attribute__ ((__cleanup__(cleanup_file)));
then ew.

But if there's a better way I really want to hear it!

(Log in to post comments)


Posted Mar 5, 2014 20:29 UTC (Wed) by mathstuf (subscriber, #69389) [Link]

It'd be nicer with "__cleanup__(func, ctx)" so you could hide all of the global variables from the function. Alternatively, wrap FILE* in a struct with the data you'd have in ctx.


Posted Mar 5, 2014 21:29 UTC (Wed) by cesarb (subscriber, #6266) [Link]

systemd's way is:

void foo(void) {
    _cleanup_fclose_ FILE *f = NULL;

Using the following definitions:

#define _cleanup_(x) __attribute__((cleanup(x)))

static inline void fclosep(FILE **p) {
    if (*p)

#define _cleanup_fclose_ _cleanup_(fclosep)

(Actually, fclosep is defined via another macro, DEFINE_TRIVIAL_CLEANUP_FUNC, but it expands to the static inline I typed above.)

Not that ugly (compare "_cleanup_fclose_ FILE *f = NULL;" with a C++ equivalent of "scoped_FILE f(nullptr);", assuming an equivalent scoped_FILE helper class). Yes, C++'s way is slightly cleaner to use (and way more complex to define), but the difference is not that big.


Posted Mar 6, 2014 18:43 UTC (Thu) by bronson (subscriber, #4806) [Link]

Hm, not bad... My overengineering spidey sense is tingling a bit but, I agree, it doesn't seem any worse than other non-GC solutions.

Looking forward to playing with these macros next time I'm waist deep in C.


Posted Mar 6, 2014 22:52 UTC (Thu) by cesarb (subscriber, #6266) [Link]

It might look like overengineering because I only showed one of the _cleanup_*_ definitions. The version of the systemd code I'm looking at has nine different _cleanup_*_ variants, four of them defined via the DEFINE_TRIVIAL_CLEANUP_FUNC macro. Search for _cleanup_ at (and pretend the rest of that file does not exist; it lives up to the tradition of a module called "util" being used as a dumping ground for assorted bits and pieces).


Posted Apr 9, 2014 13:02 UTC (Wed) by psevon (guest, #96490) [Link]

The problem with cleanup is that it doesn't allow for passing the allocated object to an outer scope and stil be subject to automatic cleanup, which is one of the main strengths of smartpointers in C++. It also doesn't work nicely together with setjmp/longjmp based exception mechanisms, since the intermediate scope (i.e., functions between the function doing setjmp and function doing longjmp in the call stack) cleanups will never be triggered. See my project for an implementation of smartpointers and exceptions in C that avoids the above mentioned problems.

Copyright © 2017, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds