Неправильная настройка и использование errno
Неправильная установка и использование errno. [1 ]
Эта проверка проверяет наличие следующих проблем:
Неправильное использование errno.
Errno не проверено.
Errno не сбрасывается.
Неправильное использование errno происходит при проверке errno для условий ошибок в ситуациях, когда проверка errno не гарантирует отсутствие ошибок. В некоторых случаях проверка errno может привести к ложным срабатываниям.
Например, вы проверяете errno следующие вызовы функций:
fopen: Если следовать стандарту ISO ®, функция может не быть установленаerrno об ошибках.
atof: При соблюдении стандарта ISO функция не устанавливается errno.
signal: errno значение указывает на ошибку, только если функция возвращает SIG_ERR индикатор ошибки.
Стандарт ISO C не обеспечивает установку этих функций errno об ошибках. Установлены ли функции errno зависит или нет от реализации.
Обнаружение ошибок при проверке errno только действительность этой проверки также становится зависимой от реализации.
В некоторых случаях errno значение указывает на ошибку, только если функция возвращает определенный индикатор ошибки. Если проверить errno перед проверкой возвращаемого значения функции можно увидеть ложные положительные результаты.
Для получения информации об обнаружении ошибок см. документацию по данной функции.
Как правило, функции возвращают внеполосный индикатор ошибок для индикации ошибок. Например:
fopen возвращает нулевой указатель при возникновении ошибки.
signal возвращает значение SIG_ERR индикатор ошибок и наборы errno до положительного значения. Проверить errno только после проверки возвращаемого значения функции.
errno После fopen Звонить#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define fatal_error() abort()
const char *temp_filename = "/tmp/demo.txt";
FILE *func()
{
FILE *fileptr;
errno = 0;
fileptr = fopen(temp_filename, "w+b");
if (errno != 0) {
if (fileptr != NULL) {
(void)fclose(fileptr);
}
/* Handle error */
fatal_error();
}
return fileptr;
}В этом примере: errno является первой переменной, которая проверяется после вызова fopen. Вы можете ожидать, что fopen изменения errno ненулевое значение при возникновении ошибки. При запуске этого кода с реализацией fopen который не установлен errno при возникновении ошибок может быть пропущено условие ошибки. В этой ситуации fopen может возвращать нулевой указатель, который скрывается от обнаружения.
fopen После вызоваОдной из возможных корректировок является проверка только возвращаемого значения fopen для нулевого указателя.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define fatal_error() abort()
const char *temp_filename = "/tmp/demo.txt";
FILE *func()
{
FILE *fileptr;
fileptr = fopen(temp_filename, "w+b");
if (fileptr == NULL) {
fatal_error();
}
return fileptr;
}Errno not checked возникает при вызове функции, которая устанавливает errno для указания условий ошибки, но не проверять errno после звонка. Для этих функций проверка errno является единственным надежным способом определить, произошла ли ошибка.
Задаваемые функции errno к ошибкам относятся:
fgetwc, strtol, и wcstol.
Полный список функций см. в документации по errno.
POSIX ®errno-установочные функции, такие как encrypt и setkey.
Чтобы убедиться, что вызов функции выполнен без ошибок, проверьте errno для значений ошибок.
Возвращаемые значения errnoФункции -setting не указывают на ошибки. Возвращаемое значение может быть одним из следующих:
void
Даже при возникновении ошибки возвращаемое значение может совпадать со значением успешного вызова. Такие возвращаемые значения называются внутриполосными индикаторами ошибок.
Определить, произошла ли ошибка, можно только путем проверки errno.
Например, strtol преобразует строку в длинное целое число и возвращает целое число. Если результат преобразования переполняется, функция возвращает LONG_MAX и наборы errno кому ERANGE. Однако функция также может возвращать LONG_MAX из успешного преобразования. Только путем проверки errno Можно ли отличить ошибку от успешного преобразования.
Перед вызовом функции установите errno до нуля.
После вызова функции, чтобы увидеть, произошла ли ошибка, сравните errno до нуля. Также можно сравнить errno к известным значениям индикаторов ошибок. Например, strtol наборы errno кому ERANGE для индикации ошибок.
Сообщение об ошибке в результате Polyspace ® показывает значение индикатора ошибки, с которым можно сравнить.
errno Не проверено после вызова strtol#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(int argc, char *argv[]) {
char *str, *endptr;
int base;
str = argv[1];
base = 10;
long val = strtol(str, &endptr, base);
printf("Return value of strtol() = %ld\n", val);
}
Используется возвращаемое значение strtol без проверки errno.
errno После вызоваПеред вызовом strtol, комплект errno до нуля. После звонка на strtol, проверьте возвращаемое значение для LONG_MIN или LONG_MAX и errno для ERANGE.
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<limits.h>
int main(int argc, char *argv[]) {
char *str, *endptr;
int base;
str = argv[1];
base = 10;
errno = 0;
long val = strtol(str, &endptr, base);
if((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE) {
printf("strtol error");
exit(EXIT_FAILURE);
}
printf("Return value of strtol() = %ld\n", val);
}
Errno not reset возникает, если не выполнить сброс errno перед вызовом функции, которая устанавливает errno для указания условий ошибки. Однако вы проверяете errno для этих ошибок после вызова функции.
errno не является чистым и может содержать значения из предыдущего вызова. Проверка errno для ошибок может создать ложное впечатление, что произошла ошибка.
errno устанавливается равным нулю при запуске программы, но впоследствии, errno не сбрасывается стандартной библиотечной функцией C. Необходимо явно задать errno до нуля при необходимости.
Перед вызовом функции, которая устанавливает errno для индикации ошибок, сброс errno до нуля явным образом.
errno Не сбрасывать перед вызовом strtod#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <float.h>
#define fatal_error() abort()
double func(const char *s1, const char *s2)
{
double f1;
f1 = strtod (s1, NULL);
if (0 == errno) {
double f2 = strtod (s2, NULL);
if (0 == errno) {
long double result = (long double)f1 + f2;
if ((result <= (long double)DBL_MAX) && (result >= (long double)-DBL_MAX))
{
return (double)result;
}
}
}
fatal_error();
return 0.0;
}В этом примере: errno не сбрасывается в 0 перед первым вызовом strtod. Проверка errno для 0 позже может привести к ложному положительному.
errno Перед вызовомОдной из возможных корректировок является сброс errno в 0 перед вызовом strtod.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <float.h>
#define fatal_error() abort()
double func(const char *s1, const char *s2)
{
double f1;
errno = 0;
f1 = strtod (s1, NULL);
if (0 == errno) {
double f2 = strtod (s2, NULL);
if (0 == errno) {
long double result = (long double)f1 + f2;
if ((result <= (long double)DBL_MAX) && (result >= (long double)-DBL_MAX))
{
return (double)result;
}
}
}
fatal_error();
return 0.0;
}| Разрешимость: неразрешимая |
[1] Выдержки из стандарта «ISO/IEC TS 17961 Technical Specification - 2013-11-15» воспроизводятся с согласия AFNOR. Нормативную ценность имеет только оригинальный и полный текст стандарта, опубликованный изданиями AFNOR - доступный через веб-сайт www.boutique.afnor.org.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.