Неправильная настройка и использование 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. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.