Пример использования атрибутов переменных
Одной из, скажем так, “нетрадиционных” возможностей, которые предоставляет GCC, являются атрибуты типов, переменных и функций.
Я хочу рассказать об одном из них — а именно, отвечающем за удаление использованных ресурсов.
Замечания по переносимости: использование конструкций, характерных для конкретного компилятора — не всегда хорошая идея, особенно, если Вы пишите переносимый код. Но очень удобно, если Вы знаете, что код всегда будет компилироваться конкретным компилятором (в нашем случае — gcc).
Что же это за магическая конструкция, позволяющая автоматом освобождать ресурсы?
А конструкция это такая:
Функция function
вызывается, когда переменная variable
уходит из области видимости. Функция принимает в качестве параметра указатель на тип, совместимый с переменной (type*
). Значение, возвращаемое функцией, игнорируется. Если функция завершается ненормально (например, вызывая исключение), дальнейшее поведение программы не определено.
Данный атрибут применим только к локальным переменным; его нельзя применять к параметрам или статическим переменным.
Использование данной конструкции найдёт почитателей среди противников goto
: если в функции есть несколько точек выхода (операторов return
), в каждой из которых нужно освобождать ресурсы, это самое то
При известной смекалке эту конструкцию можно использовать для эмуляции try…finally
.
Пример:
{
if (x && *x) free(*x);
}
void func(void)
{
char* a __attribute__((cleanup(free_char_array))) = NULL;
char* b __attribute__((cleanup(free_char_array))) = NULL;
char* c __attribute__((cleanup(free_char_array))) = NULL;
a = (char*)malloc(104857600);
if (!a) return;
b = (char*)malloc(104857600);
if (!b) return;
c = (char*)malloc(104857600);
if (!c) return;
}
Прелесть использования конструкции состоит в том, что перед return
не надо освобождать ресурсы — компилятор автоматически поместит необходимый код (как говорил один преподаватель, не нужно насиловать себе мозг, для этого есть компилятор). Недостаток заключается в том, что в любой точке выхода компилятор вызовет процедуру очистки для всех объявленных переменных (которые выходят из области видимости) с атрибутом cleanup
. То есть, если выход осуществляется после неудачного выделения памяти для переменной a
, free_char_array()
будет вызвана для всех трёх переменных (a
, b
, c
).
Мораль: переменные с атрибутом cleanup
должны иметь осмысленное значение.
спасибо очень помогло
На здоровье, доктор Дик
Не болейте
И без спама, пожалуйста.