exponenta event banner

ISO/IEC TS 17961 [инвертор]

Неправильная настройка и использование errno

Описание

Определение правила

Неправильная установка и использование errno. [1 ]

Внедрение Polyspace

Эта проверка проверяет наличие следующих проблем:

  • Неправильное использование 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;
}

Проверить информацию

Разрешимость: неразрешимая
Представлен в R2019a

[1] Выдержки из стандарта «ISO/IEC TS 17961 Technical Specification - 2013-11-15» воспроизводятся с согласия AFNOR. Нормативную ценность имеет только оригинальный и полный текст стандарта, опубликованный изданиями AFNOR - доступный через веб-сайт www.boutique.afnor.org.