Ловить коды возврата в производственных условиях? - PullRequest
2 голосов
/ 01 апреля 2009

Я хочу знать, проверять ли коды возврата для всех функций, которые мы пишем для производственной среды. для e, g я часто использую C и ловлю коды возврата и для стандартной библиотеки, не только для написанных вами функций, но и для стороннего API / стандартной библиотеки / любой другой библиотеки.

Большая часть кода, который я вижу в производстве, не делает этого. Поэтому мой вопрос к опытным людям, которые работали в производственной среде и писали производственный код около 20 лет или около того. Вы получаете код возврата от стороннего API / стандартной библиотеки / любой другой библиотеки, а не только от функций, которые вы реализуете? просто дать пример того, что я имею в виду Допустим, вы ловите коды возврата для стандартных функций библиотеки C (snprintf / sprintf, strncat / strcat и т. д., ..) стандартной библиотеки C.

Спасибо за все ваши ответы.

Ответы [ 6 ]

3 голосов
/ 01 апреля 2009

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

Я видел слишком много кода, который вызывает malloc (например) и просто с радостью использует возвращаемый указатель. В 99,9% случаев это не проблема, но иногда malloc завершается сбоем, и ваша программа падает, когда вы пытаетесь разыменовать нулевой указатель. Теперь можно утверждать, что вы хотите выйти, если malloc все равно возвращает NULL - и это может быть правдой, но вы всегда должны стараться выходить изящно, даже при фатальной ошибке.

Итак, да: проверьте коды возврата. Не думайте, что что-то работает только потому, что всегда работало в прошлом. Вещи терпят неудачу все время. Вы сэкономите много времени и скорби, защищая код, проверяя ошибки, проверяя errno, выводя strerror и отказывая изящно.

3 голосов
/ 01 апреля 2009

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

Это одна из тех областей, где следует полагаться на инженерное суждение человека, а не на предписанную «лучшую практику». Кроме того, я думаю, что то же самое относится и к обработке исключений.

2 голосов
/ 02 апреля 2009

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

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

2 голосов
/ 01 апреля 2009

Если функция может вернуть код ошибки - всегда проверяйте его и обрабатывайте так же просто, как это. Это правило может сэкономить вам много времени во время поиска ошибок.

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

1 голос
/ 01 апреля 2009

Если функция возвращает код ошибки, ваш код вызова должен решить, как обработать ошибку. Для некоторых программ игнорирование ошибки может быть в порядке; как правило, это то, что люди делают с ошибками из стандартной библиотеки ввода-вывода, например, при записи в stderr. (Что вы можете сделать, если сообщение не удалось? Выход? Вы все равно это делаете?)

Одним источником неприятностей являются функции, которые задокументированы для возврата значения, но всегда возвращают одно и то же значение (обычно 0). Часто это функции, изначально написанные на K & R C до того, как был возвращен void. Они были преобразованы в int, а затем добавлены '1007 *' к предупреждению об отключении функции 'функция не возвращает значение', вместо того, чтобы преобразовать его в void, как это и должно было быть. Такие функции должны быть пересмотрены до void; тем временем можно игнорировать возвращаемое им значение ошибки.

Я не согласен с наблюдением в другом ответе "захватывать коды возврата / ошибки, когда вы ожидаете проблем с вызовом функции". Проблема именно в том, что тебя убивает неожиданное. Даже самые стабильные операции могут неожиданно завершиться с ошибкой (может быть, СУБД вышла из строя, поэтому, даже если у вас было соединение, у вас его больше нет), и ваше программное обеспечение должно распознавать и решать такие проблемы.

0 голосов
/ 01 апреля 2009

snprintf полезно, так как вы можете выделить больший буфер, а затем повторить попытку, или вы вызываете его в следующей последовательности:

// cons lists as [a,b,c, ...]
if ( type == kin_cons_class() ) {
    size_t offs = snprintf ( buf, max, "[" );

    if ( offs >= max )
        return nul_terminate ( buf, offs, max );

    size_t count = depth;

    kin_cons_ref_t empty = kin_cons_nil();
    kin_cons_ref_t cons;

    for ( cons = ref; cons != empty; cons = kin_cons_tail ( cons ) ) {
        if ( count > 15 ) {
            offs += snprintf ( buf + offs, max - offs, ", ..." );

            break;
        }

        if ( cons != ref ) {
            offs += snprintf ( buf + offs, max - offs, "," );

            if ( offs >= max )
                return nul_terminate ( buf, offs, max );
        }

        offs += string_repr ( buf + offs, max - offs, kin_cons_head ( cons ), depth, escape_strings );

        if ( offs >= max )
            return nul_terminate ( buf, offs, max );

        ++count;
    }

    if ( offs >= max )
        return nul_terminate ( buf, offs, max );

    offs += snprintf ( buf + offs, max - offs, "]" );

    return nul_terminate ( buf, offs, max );
}

Если вы продолжите работать без всех тестов offs >= max, вы получите переполнение буфера, и оно будет зависать.

Этого не происходит с printf, поэтому реже проверяют возврат.

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

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

...