February 2021 Archives

Finally!

| No Comments

I tend to follow a standard idiom when writing C functions which allocate resources. At the top, I define a variable for each resource, and initialize it to a sentinel value meaning that it’s not yet active, and another for the function’s return value. At the bottom, I define a label end, where I release all of the resources which still seem live, and return the right result. If something goes wrong partway through, I set the return value to indicate the problem, and goto end. Easy.

But it means that the code to release a thing isn’t near where it’s defined or allocated.

I had a brainwave the other day, and wrote a macro.

#define FINALLY(body) \
  __extension__ __inline__ TMP(finally_fn) \
    (const int __attribute__((unused)) *hunoz) { body } \
  int __attribute__((unused, cleanup(TMP(finally_fn)))) \
    TMP(finally_var)

The TMP macro decorates an identifier so that it’s (more or less) private to the macro invocation. Now I can say something like

void *p = 0; FINALLY({ free(p); });

and I can use return as usual for an early exit. Yay. (Apparently I’m not the only person who’s thought of this.)

This macro has two problems.

  • Firstly, it uses nested functions, so it only works with GCC. Clang doesn’t support these, presumably because there’s no good way to implement a pointer to a nested function.

  • Secondly, the syntax is ugly, involving parentheses and a final semicolon.

I can’t figure out a way to solve both problems at the same time.

About this Archive

This page is an archive of entries from February 2021 listed from newest to oldest.

August 2018 is the previous archive.

March 2022 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Pages

OpenID accepted here Learn more about OpenID
Powered by Movable Type 5.2.13