2010-03-09 2 views
11

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

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

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

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

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

+1

Пока я нахожусь в этом, я лично отказался от '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ', ' Это спорная проблема, но если у вас нет требований к C++, я думаю, что лучше оставить ее. –

ответ

15

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

+0

Если вам не нравится видеть «goto» в вашем коде, вы всегда можете его скрыть. http://stackoverflow.com/questions/2314066/do-whilefalse – jschmier

+1

+1 Использование goto по-прежнему является лучшим способом на этом ужасном языке. – Tronic

+1

yes - это хорошая практика для кода C (в исключениях использования кода C++ и RAII). установить ресурсы ptrs в NULL; установить тогда, когда получили и иметь общую точку выхода, которая освобождает, если! NULL. Единственным недостатком является то, что это действительно заставляет вас поместить все ваши переменные ресурсов в верхнюю часть функции (я предпочитаю объявлять как можно более локально). – pm100

13

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

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

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

... 

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

3

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

Read this post for more.

2

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

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

Следует отметить, что, хотя такое решение часто подходит для автономных программ, это очень плохая идея для обработки ошибок таким образом в библиотеках - они никогда не должны прерываться неожиданно. –

0

Я склонен

  • проверки ошибок Делегат обертка функции (например, Stevens)
  • При ошибке имитации исключений с помощью longjmp. (Я на самом деле использовать Дэйв Хэнсон C Interfaces and Implementations для имитации исключений.)

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

0

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

PS: Если я еще не убедил вас: что будет, если будет принято решение, если вы должны принять тройные решения? Если это будет уродливо, но goto's ???

Смежные вопросы