Общий атрибут очистки для ошибочной памяти - PullRequest
0 голосов
/ 27 мая 2019

Имеется специфичный для GCC атрибут cleanup. Это может быть использовано так:

#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.

Я подумал, что было бы удобно иметь функцию очистки для любой malloc редактируемой памяти. Чтобы обойти проблемы с кастингом, я придумал следующую реализацию:

#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
}

Это работает, но пахнет смешно, потому что я не указываю void ** непосредственно как тип параметра, а скорее приведу к нему. Интересно, есть ли какие-то проблемы с этим, которых я сейчас не вижу.

1 Ответ

1 голос
/ 27 мая 2019

но пахнет смешно, потому что я не указываю void ** напрямую в качестве типа параметра, а скорее приведу к нему.

Приведения в C часто являются запахами кода, поэтому вы должны спросить себя: зачем необходимо приведение?

Первый подход, вероятно, будет следующим:

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

Но компилятор не позволит вам неявно преобразовать T** в void**, потому что, строго говоря, это не обязательно безопасно .

Заставление cleanup_mem взять void* и внутреннее приведение к void** не делает это преобразование более безопасным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...