
Penganalisis statis PVS-Studio mendeteksi fragmen kode yang agak rumit dan rumit yang berisi kesalahan. Dan cara memperbaikinya tidak selalu jelas bahkan bagi seseorang, dan sekarang kami akan mempertimbangkan beberapa contoh. Oleh karena itu, yang terbaik adalah tidak membuat asumsi apa pun tentang perbaikan kode otomatis sama sekali.
Terkadang programmer yang mulai mencoba PVS-Studio bertanya: mengapa alat tersebut tidak menawarkan untuk memperbaiki kesalahan secara otomatis? Menariknya, pengguna tidak lagi menanyakan pertanyaan ini. Setelah menggunakan penganalisis selama beberapa waktu, mereka menyadari bahwa untuk sebagian besar kesalahan yang terdeteksi, penggantian otomatis tidak dapat dilakukan. Setidaknya sampai kecerdasan buatan ditemukan.
Alasannya adalah PVS-Studio bukanlah penganalisis gaya kode. Itu tidak menyarankan perubahan format atau penamaan. Dia tidak menyarankan (setidaknya pada saat penulisan ini :) untuk mengganti semua NULL dalam kode C ++ dengan nullptr... Meskipun ini adalah saran yang bagus, ini hampir tidak ada hubungannya dengan pemecahan masalah.
PVS-Studio mendeteksi kesalahan dan potensi kerentanan. Banyak kesalahan yang memancing pemikiran dan membutuhkan perubahan dalam perilaku program. Dan hanya seorang programmer yang dapat memutuskan bagaimana memperbaiki kesalahan ini atau itu.
Setelah menemukan kesalahan, penganalisis kemungkinan besar akan menyarankan untuk menyederhanakan kode sehingga anomali menghilang, tetapi ini tidak akan memperbaiki kesalahan itu sendiri. Memahami apa yang sebenarnya harus dilakukan kode dan menyarankan perbaikan yang bermakna dan bermanfaat sangat sulit.
Perhatikan kesalahan yang saya analisis di artikel " 31 Februari ".
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];
}
}
Penganalisis memahami bahwa kedua pengujian itu benar. Tapi kenapa, penganalisis tidak mengerti. Dia tidak tahu apa-apa tentang hari, bulan, dan entitas lainnya. Dan untuk mengajar memahami oh, betapa sulitnya itu. Satu-satunya hal yang benar-benar dapat dilakukan adalah agar penganalisis menyarankan untuk menyederhanakan fungsi:
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;
}
}
Atau, apa yang bisa kita katakan tentang hal-hal sepele, biarkan dia menawarkan pengganti otomatis seperti itu:
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;
}
Keren, tapi tidak ada gunanya;). Penganalisis menghapus kode yang berlebihan dari sudut pandang bahasa C ++. Dan hanya satu orang yang dapat memahami apakah kode tersebut benar-benar mubazir ( dan ini juga sering terjadi ), atau ada kesalahan ketik pada kode dan perlu mengganti bulan dengan hari .
Pembaca mungkin mengatakan bahwa saya menebal dan penggantian otomatis sudah sesuai. Tidak. Orang-orang salah dalam hal ini, apa yang Anda inginkan dari program tanpa jiwa. Lihat, ada contoh menarik dari pengeditan manual yang lalai yang sebenarnya tidak memperbaiki apa pun. Karena seseorang tidak bisa, begitu pula program.
Di bulan Agustus tahun viral ini, saya menulis artikeltentang memeriksa perpustakaan PMDK. Antara lain, artikel tersebut menganggap kesalahan perlindungan luapan yang salah:
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;
}
Karena rel_wait adalah tipe unsigned, pemeriksaan selanjutnya untuk rel_wait <0 tidak ada artinya. Peringatan PVS-Studio: V547 [CWE-570] Ekspresi 'rel_wait <0' selalu salah. Nilai jenis unsigned tidak pernah <0. os_thread_windows.c 359
Seseorang terinspirasi oleh artikel tersebut dan mulai memperbaiki kesalahan yang dijelaskan di dalamnya secara besar-besaran: Perbaiki berbagai masalah yang dilaporkan oleh analisis PVS-Studio .
Dan bagaimana cara memperbaiki kode tersebut? Cukup sederhana: inti: menyederhanakan implementasi pengatur waktu windows .

Tetapi kodenya disederhanakan, tidak diperbaiki! Ini telah diperhatikan dan diskusi terkait dimulai: MASALAH: os_thread_windows.c - get_rel_wait () akan memblokir jika abstime ada di masa lalu .
Seperti yang Anda lihat, bahkan orang membuat kesalahan dalam pengeditan yang disarankan. Dimana robot bisa mencoba.
Bagaimanapun, keinginan untuk memperbaiki kesalahan secara otomatis adalah keinginan yang sangat aneh. Setiap perubahan yang memperbaiki bug membutuhkan perhatian dan peninjauan kode. Selain itu, penganalisis dapat memberikan positif palsu, yang berarti Anda tidak dapat mengedit kode tersebut sama sekali. Menganalisis kode Anda dan menangani peringatan bukanlah tempat untuk terburu-buru. Lebih baik menerapkan analisis kode biasa dan secara perlahan memperbaiki bug yang muncul di kode baru.

Jika Anda ingin berbagi artikel ini dengan audiens berbahasa Inggris, silakan gunakan tautan terjemahan: Andrey Karpov. Mengapa PVS-Studio Tidak Menawarkan Perbaikan Otomatis .