Установка Incorrectly и использующий 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, не проверяемый, происходит, когда вы вызываете функцию, которая устанавливает 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 не сбрасывают, происходит, когда вы не сбрасываете 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 - 2013-11-15" воспроизводятся с соглашением о AFNOR. Только исходный и полный текст стандарта, как опубликовано Выпусками AFNOR - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.