
PVS-Studio静的アナライザーは、エラーを含むかなり複雑でトリッキーなコードフラグメントを検出します。そして、それらを修正する方法は、人にとっても必ずしも明確ではありません。ここで、いくつかの例を検討します。したがって、自動コード修正に関する仮定をまったく生成しないことが最善です。
PVS-Studioを 試し始めたプログラマーは、次のように尋ねることがあります。ツールがエラーを自動的に修正することを提供しないのはなぜですか。興味深いことに、ユーザーはもはやこの質問をしません。しばらくの間アナライザーを使用した後、彼らは、検出されたエラーの大部分について、自動置換が不可能であることに気付きました。少なくとも人工知能が発明されるまでは。
その理由は、PVS-Studioがコードスタイルアナライザーではないためです。フォーマットや名前の変更を示唆するものではありません。彼は(少なくともこの記事の執筆時点では:) C ++コードのすべてのNULLをnullptrに置き換えることを提案していません。..。これは良い提案ですが、トラブルシューティングとはほとんど関係ありません。
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 ++言語の観点から冗長なコードを削除しました。そして、コードが本当に冗長であるかどうか(そしてこれも頻繁に発生します)、またはコードにタイプミスがあり、月を日で置き換える必要があるかどうかを理解できるのは人だけです。
読者は私が肥厚していると言うかもしれません、そして自動交換は適切です。番号。人々はこれに誤解されています、あなたは魂のないプログラムから何を望むことができますか。ほら、実際には何も修正しない手動の不注意な編集の興味深い例があります。人はできないので、プログラムもできません。
このバイラルイヤーの8月に、私は記事を書きました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.c359
誰かが記事に触発され、記事に記載されているエラーを大幅に修正し始めました。PVS -Studio分析によって報告されたさまざまな問題を修正します。
そして、コードを修正することはどのように提案されましたか?非常に単純:コア:Windowsタイマーの実装を簡素化します。

しかし、コードは単純化されており、修正されていません。これに気づき、対応する議論が始まりました。問題:os_thread_windows.c-abstimeが過去の場合、get_rel_wait()はブロックされます。
ご覧のとおり、提案された編集で間違いを犯す人もいます。なぜロボットを試すのか。
とにかく、エラーを自動的に修正したいという願望は非常に奇妙な願望です。バグを修正するすべての変更には、注意とコードのレビューが必要です。さらに、アナライザーは誤検知を出す可能性があります。つまり、そのようなコードはまったく編集できません。コードを分析して警告に対処することは、急ぐ場所ではありません。定期的なコード分析を実装し、新しいコードに現れるバグをゆっくりと修正することをお勧めします。

この記事を英語を話す聴衆と共有したい場合は、翻訳リンクを使用してください:AndreyKarpov。PVS-Studioが自動修正を提供しない理由。