警告 C26864

日期-时间对象 var 的日期字段已修改,假设每年 365 天,没有正确的闰年检查:expr

此规则是在 Visual Studio 2022 17.8 中添加的。

备注

在公历中,每个能被 4 整除的年份都是闰年,但能被 100 整除的年份除外。 如果百年年份能被 400 整除,那么它们也是闰年。

当软件未考虑此闰年逻辑或使用有缺陷的逻辑时,就会出现闰年 bug。 这可能会影响相关系统的可靠性、可用性甚至安全性。

对表示日期的变量执行算术运算时,必须考虑闰年。 一年有 365 天的假设并不可靠。 闰年有 366 天,因为 2 月添加了“闰日”作为第 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