Подтвердить что ты не робот

Портативный эквивалент gcc __attribute __ (очистка)

Недавно я наткнулся на расширение gcc, которое я нашел довольно полезным: __attribute__(cleanup)

В принципе, это позволяет назначить вызов очистки локальной переменной в момент выхода из области. Например, в следующем разделе кода вся память должна поддерживаться и обрабатываться явно в любом случае во время вызова foo.

void foo() {
   char * buff = ...; /* some memory allocation */
   char * buff2 = 0, * buff3 = 0;
   if (! buff) {
      return;
   } else {
      buff2 = ...; /* memory allocation */
      if (! buff2) {
         goto clean_exit;
      } else {
         /* ... and so on ... */
      }
   }

clean_exit:
   free (buff);
   free (buff2);
   free (buff3);
}

Однако, используя расширение, которое можно уменьшить до

#define clean_pchar_scope __attribute__((cleanup(pchar_free)))

void pchar_free (char ** c) { free (*c); }

void foo () {
   char * buff clean_pchar_scope = ...; /* some memory allocation */
   char * buff2 clean_pchar_scope = 0, * buff3 clean_pchar_scope = 0;
   if (! buff)
      return;
   buff2 = ...; /* memory allocation */
   if (! buff2)
      return;
   /* and so on */
}

Теперь вся память восстанавливается на основе области без использования вложенных конструкций if/else или goto в сочетании с секцией освобождения консолидированной памяти функции. Я понимаю, что использование goto можно было бы избежать там для более вложенной конструкции if/else (так что, пожалуйста, никаких священных войн на goto...), и что этот пример надуман, но факт остается фактом: это может быть довольно полезная функция.

К сожалению, насколько я знаю, это спецификация gcc. Меня интересуют любые переносные способы сделать то же самое (если они даже существуют). Кто-нибудь имел опыт в этом с чем-то отличным от gcc?

EDIT: Кажется, что переносимость не в игре. Учитывая, что есть ли способ сделать это за пределами gcc-пространства? Кажется приятной особенностью быть gcc-специфической...

4b9b3361

Ответ 1

В C нет переносного способа.

К счастью, это стандартная функция С++ с деструкторами.

Edit:

У MSVC есть слова __try и __finally, которые могут быть использованы для этой цели. Это отличается от обработки исключений С++, и я думаю, что он доступен в C.

Я думаю, вы обнаружите, что очистка и попытка /, наконец, широко не используются специально из-за неявной поддержки на С++, которая достаточно близка к C, что люди, заинтересованные в поведении, могут переключать свой код на С++ с помощью легкость.

Ответ 2

Первая половина вашего вопроса - это переносимый способ сделать это.

Ответ 3

void foo()
{
        char *buf1 = 0, *buf2 = 0, *buf3 = 0;
        /** more resource handle */

        do {

                if ( buf1 = ... , !buf1 ) break;
                if ( buf2 = ... , !buf2 ) break;
                if ( buf3 = ... , !buf3 ) break;

                /** to acquire more resource */

                /** to do with resource */

        } while (0);

        /** to release more resource */

        if (buf3) free(buf3);
        if (buf2) free(buf2);
        if (buf1) free(buf1);
}

Ответ 4

Вы можете использовать boost:: shared_ptr для этой цели.

boost::shared_ptr<char> buffer(p, cleanup);