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

Примеры

развернуть все

#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;
}

Информация о результате

Группа: Программирование
Язык: C | C++
Значение по умолчанию: на
Синтаксис командной строки: ERRNO_MISUSE
Влияние: высоко
ID CWE: 703

Введенный в R2017a