Pull to refresh

Comments 5

Хороший пример использования этого атрибута – critical section в атмеловской либе для atmega/attiny.

С __attribbute__(( cleanup(...) )) могут быть нюансы, связанные с повторным заходом в область видимости.
Пример:
int main(void)
{
  {
    struct Obj *test __attribute__(( cleanup(Obj_cleanup) )) = calloc(1, sizeof(struct Obj));
    fprintf(stdout, "Obj allocated at %p\n", (void*)test);
    
    fprintf(stdout, "Quitting the test scope...\n");
    goto main__sub1;
  
main__exit:
    return 0;
  } // <-- Obj_cleanup is executed here twice, even though the control flow passes the 'test' definition only once

main__sub1:
  fprintf(stdout, "The test scope has been quit.\n");
  goto main__exit;
}

Вывод:
Obj allocated at 00000000005F6880
Quitting the test scope…
Obj_cleanup() for 00000000005F6880
The test scope has been quit.
Obj_cleanup() for 00000000005F6880

А вот clang отслеживает наличие на границе области видимости выполняющейся cleanup-функции, зависящей от переменной test, и отказывается компилировать такой код.
int *ptr_one = (int *)malloc(sizeof(int));

  1. Не стоит преобразовывать явно возвращаемое значение malloc — это Си, а не Си++, и здесь void * приводится к любому указателю: void * для этого и придуман.
  2. Не стоит в данной конструкции использовать sizeof(int), конструкция sizeof(*ptr_one) уменьшает число точек отказа при поддержке кода.

Например, при смене типа переменной (int * на long * — как вариант), если выполнить пункты выше — вся конструкция останется валидной. (А лучше, если здесь будет указатель на структурный объект.)


Если оставить как есть, то рано или поздно кто-нибудь да забудет исправить размер выделяемой памяти, а явное преобразование типа запретит умному компилятору выдать предупреждение об этом (так как явное преобразование — это «делай как я сказал» в Си).

Sign up to leave a comment.

Articles