PVS-Studio静态分析器检测包含错误的相当复杂且棘手的代码片段。甚至对于一个人来说,如何解决它们也不总是很清楚,现在我们将考虑几个示例。因此,最好根本不产生关于自动代码修复的任何假设。
有时开始尝试PVS-Studio的程序员会问:为什么该工具没有提供自动修复错误的功能?有趣的是,用户不再问这个问题。使用分析仪一段时间后,他们意识到对于大多数检测到的错误,无法自动更换。至少直到发明了人工智能。
原因是PVS-Studio不是代码样式分析器。它不建议格式化或命名更改。他不建议(至少在撰写本文时:)用nullptr替换C ++代码中的所有NULL。...虽然这是一个很好的建议,但它与故障排除几乎没有任何关系。
PVS-Studio可检测错误和潜在漏洞。许多错误是发人深省的,需要更改程序行为。而且只有程序员才能决定如何解决这个或那个错误。
发现错误后,分析器很可能会建议简化代码,以使异常消失,但这无法修复错误本身。理解代码实际上应该做什么并提出有意义的,有用的修复方法非常困难。
考虑一下我在文章“ 2月31日”中讨论的错误。
static const int kDaysInMonth[13] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
bool ValidateDateTime(const DateTime& time) {
if (time.year < 1 || time.year > 9999 ||
time.month < 1 || time.month > 12 ||
time.day < 1 || time.day > 31 ||
time.hour < 0 || time.hour > 23 ||
time.minute < 0 || time.minute > 59 ||
time.second < 0 || time.second > 59) {
return false;
}
if (time.month == 2 && IsLeapYear(time.year)) {
return time.month <= kDaysInMonth[time.month] + 1;
} else {
return time.month <= kDaysInMonth[time.month];
}
}
分析仪知道这两个测试都是正确的。但是为什么,分析仪不明白。他对日子,月份和其他实体一无所知。并要教懂这样的哦,这有多难。真正可以做的唯一事情就是让分析仪建议简化功能:
bool ValidateDateTime(const DateTime& time) {
if (time.year < 1 || time.year > 9999 ||
time.month < 1 || time.month > 12 ||
time.day < 1 || time.day > 31 ||
time.hour < 0 || time.hour > 23 ||
time.minute < 0 || time.minute > 59 ||
time.second < 0 || time.second > 59) {
return false;
}
if (time.month == 2 && IsLeapYear(time.year)) {
return true;
} else {
return true;
}
}
或者,我们可以在琐事上说些什么,让他提供这种自动替换:
bool ValidateDateTime(const DateTime& time) {
if (time.year < 1 || time.year > 9999 ||
time.month < 1 || time.month > 12 ||
time.day < 1 || time.day > 31 ||
time.hour < 0 || time.hour > 23 ||
time.minute < 0 || time.minute > 59 ||
time.second < 0 || time.second > 59) {
return false;
}
return true;
}
很酷,但毫无意义;)。从C ++语言的角度来看,分析器删除了多余的代码。而只有一个人能理解的代码是否真的是多余的(这也经常发生),或者出现在代码中的错字,这是需要更换月与日。
读者可能会说我正在加厚,因此自动更换是合适的。没有。人们误会了这一点,您可以从一个没有灵魂的程序中得到什么。看,有一个有趣的例子,它是一个手动的,不专心的编辑,实际上并不能解决任何问题。由于一个人不能,所以程序也不能。
在这个病毒年的八月,我写了一篇文章关于检查PMDK库。其中,本文考虑了错误的溢出保护错误:
static DWORD
get_rel_wait(const struct timespec *abstime)
{
struct __timeb64 t;
_ftime64_s(&t);
time_t now_ms = t.time * 1000 + t.millitm;
time_t ms = (time_t)(abstime->tv_sec * 1000 +
abstime->tv_nsec / 1000000);
DWORD rel_wait = (DWORD)(ms - now_ms);
return rel_wait < 0 ? 0 : rel_wait;
}
由于rel_wait是无符号类型,因此后续检查rel_wait <0是没有意义的。 PVS-Studio警告:V547 [CWE-570]表达式'rel_wait <0'始终为false。无符号类型的值永远不会小于0. os_thread_windows.c 359
有人从本文中获得启发,并开始大量修复其中描述的错误:修复PVS-Studio分析报告的各种问题。
并建议如何修复代码?很简单:核心:简化Windows计时器的实现。
但是代码是简化的,不是固定的!注意到这一点,并开始了相应的讨论:问题:如果abstime在过去,则os_thread_windows.c-get_rel_wait()将阻塞。
如您所见,即使有人在建议的编辑中犯错。机器人可以在哪里尝试。
无论如何,自动纠正错误的愿望是一个非常奇怪的愿望。修复错误的每个更改都需要引起注意和代码审查。此外,分析器可能会给出误报,这意味着您根本无法编辑此类代码。分析您的代码并处理警告并不是急事。最好执行常规代码分析并慢慢修复出现在新代码中的错误。
如果您想与说英语的读者分享这篇文章,请使用翻译链接:Andrey Karpov。为什么PVS-Studio不提供自动修复。