Поделиться через


Предупреждение C26864

Поле дня объекта var даты и времени было изменено при условии, что 365 дней в год без надлежащей проверки високосного года: expr

Это правило было добавлено в Visual Studio 2022 17.8.

Замечания

В григорианском календаре каждый год точно делится на четыре високосный год, за исключением лет, которые точно делятся на 100. Вековые годы также високосные годы, если они точно делятся на 400.

Ошибка високосного года возникает, когда программное обеспечение не учитывает логику этого високосного года или использует несовершенную логику. Это может повлиять на надежность, доступность или даже безопасность затронутой системы.

При выполнении арифметических операций с переменной, представляющей дату, необходимо учитывать високосные годы. Небезопасно предположить, что год составляет 365 дней. Вискочий год имеет 366 дней из-за "викосного дня" добавлен в качестве 29-го дня в феврале.

Чтобы правильно продвинуться в год, определите, содержит ли интервал времени високосный день, а затем выполните вычисление с использованием правильного количества дней. Лучше, если год напрямую продвинулся, с соответствующим високосным днём проверки на результирующий день. Кроме того, используйте установленную подпрограмму библиотеки, которая правильно обрабатывает високосные годы.

Имя анализа кода: DATETIME_MANIPULATION_ASSUMING_365_DAYS_WITHOUT_LEAPYEAR_CHECK

Пример

Следующий код пытается получить текущее системное время, перейти на день к одному году, добавив 365 дней в поле дня и изменив дату в високосное правило года. Однако результат может не совпадать с тем же месяцем или датой следующего года:

#include <Windows.h> 
 
void foo() 
{ 
    SYSTEMTIME st; 

    GetSystemTime(&st); 

    // Advance a year by adding 365 days 
    st.wDay += 365;    // C26864 
}

Чтобы устранить эту проблему, перейдите к полю года непосредственно и настройте дату в течение високосного правила года:

#include <Windows.h> 
 
void foo() 
{ 
    SYSTEMTIME st; 
    GetSystemTime(&st); 

    st.wYear++; // Advance a year 

    // Adjust the date
    if (st.wMonth == 2 && st.wDay == 29) 
    { 
        // Move back a day when landing on Feb 29 in a non-leap year 
        bool isLeapYear = st.wYear % 4 == 0 && (st.wYear % 100 != 0 || st.wYear % 400 == 0); 
        if (!isLeapYear) 
        { 
            st.wDay = 28; 
        } 
    } 
}

Эвристика

Это правило распознает только структуру Windows SYSTEMTIME и структуру C tm .

Это правило применяется, если поле даты изменяется непосредственно на 365 дней. Он не учитывает, назначается ли значение поля даты другой переменной, а затем управляется и поэтому может пропустить эквивалентные ошибки.

Это правило является правилом согласия, т. е. анализ кода должен использовать файл набора правил, и правило должно быть явно включено в файл набора правил и включено для его применения. Дополнительные сведения о создании пользовательского набора правил для анализа кода см. в разделе "Использование наборов правил для указания C++ правил для выполнения".

См. также

C6393
C6394
C26861
C26862
C26863