警告 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++
规则。