0

There is GCC-specific attribute cleanup. It might be used like this:

#define SCOPED_FILE __attribute__((cleanup(cleanup_file)))

void
cleanup_file(FILE **file) {
    if (*file != NULL) { fclose(*file); }
}
…
FILE *SCOPED_FILE file = fopen(…); // file will be closed at the end of scope.

I thought it would be handy to have cleanup function for any malloced memory. Having to circumvent casting issues, I came up with the following implementation:

#define SCOPED_MEM __attribute__((cleanup(cleanup_mem)))

static inline void
cleanup_mem(void *pmem) {
    void *mem = *(void **)pmem;
    free(mem);
}

int main(void) {
    char *SCOPED_MEM str = malloc(20);
    strcpy(str, "pineapple");
    printf("hi, %s\n", str);
    // str will be free'd at the end of scope
}

It does work, but smells funny, because I don't directly specify void ** as parameter type, but rather cast to it. I wonder, if there are some problems with it that I don't see right now.

grepcake
  • 3,960
  • 3
  • 16
  • 26

1 Answers1

1

but smells funny, because I don't directly specify void ** as parameter type, but rather cast to it.

Casts in C are often code smells, so you should ask yourself: why is the cast necessary?

One's first approach probably would be:

static inline void
cleanup_mem(void **pmem) {
    free(*mem);
}

But the compiler won't let you implicitly convert T** to void** because, strictly speaking, it's not necessarily safe.

Making cleanup_mem take a void* and internally cast to void** doesn't make that conversion any safer.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • So, it's not possible to do what I want? Besides further limiting platform choice. – grepcake May 27 '19 at 17:50
  • @grepcake In practice, the `void**` cast probably should be okay (but your code should verify that `sizeof (T**) == sizeof (void **)` as a precaution), so I wouldn't worry too much about it. Using a `gcc` extension already limits portability anyway. Personally I would just write portable code using [a single-entry, single-exit idiom with `goto`](https://stackoverflow.com/a/30007860/179715). – jamesdlin May 27 '19 at 18:03