хорошие c разрабатывают при проверке большого количества возвращаемых значений

Иногда я должен написать код, который чередуется между выполнением вещей и проверкой состояния ошибки (например, назовите библиотечную функцию, проверьте ее возвращаемое значение, продолжайте идти). Это часто приводит к длительным периодам, где фактическая работа происходит в условиях если операторы, как

if(! (data = (big_struct *) malloc(sizeof(*data)))){
    //report allocation error
} else if(init_big_struct(data)){
    //handle initialization error
} else ...

Как делают Вас, парни пишут этот вид кода? Я проверил несколько руководств по стилю, но они кажутся более соответствующими с переменным именованием и пробелом.

Ссылки на приветствующиеся руководства по стилю.

Править: в случае, если это не ясно, я неудовлетворен четкостью этого стиля и поиска чего-то лучше.

11
задан Wang 9 March 2010 в 18:51
поделиться

6 ответов

Хотя мне больно это говорить, это может быть случай никогда не пользовавшегося популярностью goto . Вот одна ссылка, которую я нашел по этой теме: http://eli.thegreenplace.net/2009/04/27/using-goto-for-error-handling-in-c/

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

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

void * Malloc(size_t size) {
    void    *ptr;
    if ( (ptr = malloc(size)) == NULL)
        err_sys("malloc error");
    return(ptr);
}

err_sys здесь отображает ошибка, а затем выполняет exit (1) . Таким образом, вы можете просто вызвать Malloc и знать, что он выдаст ошибку, если возникнет проблема.

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

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

Я предпочитаю

  • Делегировать проверку ошибок функциям-оболочкам (например, Стивенсу)
  • В случае ошибки моделировать исключения с помощью longjmp . (На самом деле я использую интерфейсы и реализации C Дейва Хэнсона для имитации исключений.)

Другой вариант - использовать грамотное программирование Дона Кнута для управления кодом обработки ошибок или что-то другое. своего рода препроцессор. Эта опция доступна только в том случае, если вы можете установить правила для своего магазина: -)

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

Я обычно пишу этот код таким образом:

data = (big_struct *) malloc(sizeof(*data));
if(!data){
    //report allocation error
    return ...;
}

err = init_big_struct(data);
if(err){
    //handle initialization error
    return ...;
}

...

Таким образом я избегаю вызова функций внутри if, а отладка упрощается, потому что вы можете проверить возвращаемые значения.

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

Единственное группирующее свойство такого кода состоит в том, что существует просто внешне навязанная последовательность, которой он должен следовать. Вот почему вы помещаете эти выделения в одну функцию, но это очень слабая общность. Почему некоторые люди рекомендуют отказаться от преимуществ вложенных if, я не понимаю. Вы эффективно пытаетесь накрасить свинью помадой (без оскорбления) - природа кода никогда не даст ничего чистого, лучшее, что вы можете сделать, - это использовать компиляторы, помогающие отлавливать (обслуживающие) ошибки. ИМХО, придерживайтесь «если».

PS: если я еще не убедил вас: как будет выглядеть решение goto, если вам придется принимать тройные решения? Если, конечно, станет еще уродливее, но вот goto ???

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

Не используйте assert в production-коде.
В режиме отладки assert никогда не должен использоваться для того, что может произойти (например, malloc возвращает NULL), скорее он должен использоваться в невозможных случаях (например, индекс массива выходит за границы в C)

Read this post for more.

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

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