Макросы управления потока с 'goto'

В файл application.properties добавьте

server.port=1089

, вы также можете настроить порт программно

@Configuration
public class ServletConfig {
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return (container -> {
            container.setPort(1089);
        });
    }
}

или в качестве параметра командной строки:

-Dserver.port=1089
6
задан sharkin 1 April 2009 в 09:10
поделиться

9 ответов

Обработка ошибок является одной из редких ситуаций когда goto не так плохо.

Но если бы я должен был поддержать тот код, то я был бы очень расстроен это goto скрыты макросами.

Так в этом случае goto хорошо для меня, но не макросов.

11
ответ дан 8 December 2019 в 02:30
поделиться

Этот код:

void func()
{
   char* p1 = malloc(16);
   if( !p1 )
      goto cleanup;

   char* p2 = malloc(16);
   if( !p2 )
      goto cleanup;

 cleanup:

   if( p1 )
      free(p1);

   if( p2 )
      free(p2);
}

может быть по закону записан как:

void func()
{
   char* p1 = malloc(16);
   char* p2 = malloc(16);

    free(p1);
    free(p2);
}

успешно выполняются ли выделения памяти.

Это работает, потому что свободный () ничего не делает, если передано Нулевой указатель. Можно использовать ту же идиому при разработке собственных API, чтобы выделить и освободить другие ресурсы:

// return handle to new Foo resource, or 0 if allocation failed
FOO_HANDLE AllocFoo();

// release Foo indicated by handle, - do nothing if handle is 0
void ReleaseFoo( FOO_HANDLE h );

Разработка API как это может значительно упростить управление ресурсами.

7
ответ дан 8 December 2019 в 02:30
поделиться

Используя goto перейти к последовательности обработчика/очистки/выхода распространенных ошибок прекрасно абсолютно.

8
ответ дан 8 December 2019 в 02:30
поделиться

Очистка с goto общая идиома C и используется в Linux kernel*.

** Возможно, мнение Linus не является лучшим примером хорошего аргумента, но это действительно показывает goto будучи используемым в относительно крупномасштабном проекте.*

3
ответ дан 8 December 2019 в 02:30
поделиться

Если первый malloc приводит Вас к сбою затем очистка и p1 и p2. Из-за goto, p2 не инициализируется и может указать на что-либо. Я работал, это быстро с gcc для проверки и пытающийся к свободному (p2) действительно вызовет отказ seg.

В Вашем последнем примере переменные ограничены по объему в фигурных скобках (т.е. они только существуют в блоке FAIL_SECTION_BEGIN).

Принятие кода работает без фигурных скобок, необходимо было бы все еще инициализировать все указатели на ПУСТОЙ УКАЗАТЕЛЬ перед FAIL_SECTION_BEGIN для предотвращения сбоя seg.

У меня ничего нет против goto и макросов, но я предпочитаю идею Neil Butterworth..

void func(void)
{
    void *p1 = malloc(16);
    void *p2 = malloc(16);
    void *p3 = malloc(16);

    if (!p1 || !p2 || !p3) goto cleanup;

    /* ... */

cleanup:
    if (p1) free(p1);
    if (p2) free(p2);
    if (p3) free(p3);
}

Или если это является более соответствующим..

void func(void)
{
    void *p1 = NULL;
    void *p2 = NULL;
    void *p3 = NULL;

    p1 = malloc(16);
    if (!p1) goto cleanup;

    p2 = malloc(16);
    if (!p2) goto cleanup;

    p3 = malloc(16);
    if (!p3) goto cleanup;

    /* ... */

cleanup:
    if (p1) free(p1);
    if (p2) free(p2);
    if (p3) free(p3);
}
3
ответ дан 8 December 2019 в 02:30
поделиться

Термин "Структурное программирование", которое все мы знаем как anti-goto вещь, первоначально запущенную и разработанную как набор кодирования шаблонов с goto's (или JMP's). Те шаблоны назвали while и if шаблоны, среди других.

Так, при использовании goto's используйте их структурированным способом. Это ограничивает повреждение. И они макрос кажутся разумным подходом.

2
ответ дан 8 December 2019 в 02:30
поделиться

Первый пример выглядит намного более читаемым мне, чем macroised версия. И mouviciel сказал это намного лучше, чем я

1
ответ дан 8 December 2019 в 02:30
поделиться

Исходный код извлек бы выгоду из использования нескольких операторов возврата - нет никакой потребности скачкообразно двинуться вокруг ошибочного возврата, очищают код. Плюс, Вам обычно нужно выделенное пространство, освобожденное по обычному возврату также - иначе Вы пропускаете память. И можно переписать пример без goto если Вы осторожны. Это - случай, где можно полезно объявить переменные прежде в других отношениях необходимый:

void func()
{
    char *p1 = 0;
    char *p2 = 0;
    char *p3 = 0;

    if ((p1 = malloc(16)) != 0 &&
        (p2 = malloc(16)) != 0 &&
        (p3 = malloc(16)) != 0)
    {
        // Use p1, p2, p3 ...
    }
    free(p1);
    free(p2);
    free(p3);
}

Когда существуют нетривиальные объемы работы после каждой операции выделения, затем можно использовать маркировку перед первый из free() операции и a goto в порядке - обработка ошибок является главной причиной для использования goto в эти дни, и что-либо очень еще несколько сомнительно.

Я забочусь о некотором коде, который действительно имеет макросы со встроенными операторами перехода. Это сбивает с толку на первом обнаружении для наблюдения маркировки, которая является 'не имеющей ссылки' видимым кодом, все же который не может быть удален. Я предпочитаю избегать таких методов. Макросы в порядке, когда я не должен знать то, что они делают - они просто делают это. Макросы не так в порядке, когда необходимо знать то, до чего они расширяются использовать их точно. Если они не скрывают информацию от меня, они - больше неприятности, чем справка.

Иллюстрация - имена, замаскированные для защиты виновного:

#define rerrcheck if (currval != &localval && globvar->currtub &&          \
                    globvar->currtub->te_flags & TE_ABORT)                 \
                    { if (globvar->currtub->te_state)                      \
                         globvar->currtub->te_state->ts_flags |= TS_FAILED;\
                      else                                                 \
                         delete_tub_name(globvar->currtub->te_name);       \
                      goto failure;                                        \
                    }


#define rgetunsigned(b) {if (_iincnt>=2)  \
                           {_iinptr+=2;_iincnt-=2;b = ldunsigned(_iinptr-2);} \
                         else {b = _igetunsigned(); rerrcheck}}

Существует несколько дюжин вариантов на rgetunsigned() это несколько подобно - различные размеры и различные функции загрузчика.

Одно место, где они используются, содержит этот цикл - в большем блоке кода в единственном случае большого переключателя с некоторыми маленькими и некоторых больших блоках кода (не особенно хорошо структурированный):

        for (i = 0 ; i < no_of_rows; i++)
            {
            row_t *tmprow = &val->v_coll.cl_typeinfo->clt_rows[i];

            rgetint(tmprow->seqno);
            rgetint(tmprow->level_no);
            rgetint(tmprow->parent_no);
            rgetint(tmprow->fieldnmlen);
            rgetpbuf(tmprow->fieldname, IDENTSIZE);
            rgetint(tmprow->field_no);
            rgetint(tmprow->type);
            rgetint(tmprow->length);
            rgetlong(tmprow->xid);
            rgetint(tmprow->flags);
            rgetint(tmprow->xtype_nm_len);
            rgetpbuf(tmprow->xtype_name, IDENTSIZE);
            rgetint(tmprow->xtype_owner_len);
            rgetpbuf(tmprow->xtype_owner_name, IDENTSIZE);
            rgetpbuf(tmprow->xtype_owner_name,
                     tmprow->xtype_owner_len);
            rgetint(tmprow->alignment);
            rgetlong(tmprow->sourcetype);
            }

Не очевидно, что код там пропитан операторами перехода! И ясно, полное толкование грехов кода, из которого это прибывает, весь день брало бы - они - многие и варьировались.

1
ответ дан 8 December 2019 в 02:30
поделиться
#define malloc_or_die(size) if(malloc(size) == NULL) exit(1)

Это не похоже на то, что вы действительно можете восстановиться после сбоя malloc, если у вас нет программного обеспечения, достойного написания системы транзакций, если вы добавите код отката в malloc_or_die.

Для реального примера Правильное использование goto, проверьте код отправки, который использует вычисленное goto.

0
ответ дан 8 December 2019 в 02:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: