Неправильная настройка и использование errno
Неправильная настройка и использование errno.[1]
Эта проверка проверяет на наличие следующих проблем:
Неправильное использование errno.
Эрно не проверяется.
Errno не сбрасывается.
Неправильное использование errno происходит при проверке errno
для условий ошибки в ситуациях, когда проверка errno
не гарантирует отсутствие ошибок. В некоторых случаях проверка errno
может привести к ложным срабатываниям.
Например, вы проверяете errno
следующие вызовы функций:
fopen
: Если вы следуете ISO® Стандартная, функция может не устанавливаться errno
об ошибках.
atof
: Если вы следуете стандарту ISO, функция не устанавливается errno
.
signal
: The errno
значение указывает на ошибку, только если функция возвращает SIG_ERR
индикатор ошибки.
Стандарт ISO C не обеспечивает, чтобы эти функции errno
об ошибках. Устанавливаются ли функции errno
или нет зависит от реализации.
Чтобы обнаружить ошибки, если вы проверяете errno
только валидность этой проверки также становится зависимой от реализации.
В некоторых случаях errno
значение указывает на ошибку, только если функция возвращает определенный индикатор ошибки. Если вы проверяете errno
перед проверкой возвращаемого значения функции можно увидеть ложные срабатывания.
Для получения информации о том, как обнаружить ошибки, смотрите документацию для этой конкретной функции.
Как правило, функции возвращают внеполосный индикатор ошибки, чтобы указать на ошибки. Для образца:
fopen
возвращает указатель null, если произошла ошибка.
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
для указателя со значением null.
#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 не проверяется, когда вы вызываете функцию, которая устанавливает errno
чтобы указать условия ошибки, но не проверяйте errno
после вызова. Для этих функций проверяйте errno
является единственным надежным способом определить, произошла ли ошибка.
Функции, которые задают errno
при ошибках включают:
fgetwc
, strtol
, и wcstol
.
Полный список функций см. в документации об errno.
POSIX® errno
-настройка функций, таких как encrypt
и setkey
.
Чтобы увидеть, завершен ли вызов функции без ошибок, проверьте errno
для значений ошибок.
Значения возврата этих errno
-настройка функций не указывает на ошибки. Значение возврата может быть одним из следующих:
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 сброс происходит, когда вы не сбрасываете errno
перед вызовом функции, которая устанавливает errno
для указания условий ошибки. Однако вы проверяете errno
для условий ошибки после вызова функции.
The 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; }
Решимость: Undecidable |
[1] Выдержки из стандарта «Техническая спецификация ISO/IEC TS 17961 - 2013-11-15» воспроизводятся с согласия АФНОР. Только оригинальный и полный текст стандарта, опубликованный AFNOR Editions - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.